зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i.
This commit is contained in:
Коммит
97ae827742
6
CLOBBER
6
CLOBBER
|
@ -15,8 +15,6 @@
|
|||
#
|
||||
# Note: The description below will be part of the error message shown to users.
|
||||
#
|
||||
# *** Important! ***
|
||||
# If changing this file you must manually clobber immediately before landing,
|
||||
# (due to bug 837323), using: https://secure.pub.build.mozilla.org/clobberer/
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 737100 broke Windows builds.
|
||||
Bug 855350 broke Windows builds.
|
||||
|
|
|
@ -279,8 +279,8 @@ this.UtteranceGenerator = {
|
|||
application: function application(aAccessible, aRoleStr, aStates, aFlags) {
|
||||
// Don't utter location of applications, it gets tiring.
|
||||
if (aAccessible.name != aAccessible.DOMNode.location)
|
||||
return this.objectUtteranceFunctions.defaultFunc(
|
||||
aAccessible, aRoleStr, aStates, aFlags);
|
||||
return this.objectUtteranceFunctions.defaultFunc.apply(this,
|
||||
[aAccessible, aRoleStr, aStates, aFlags]);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -214,46 +214,7 @@ var Browser = {
|
|||
}
|
||||
},
|
||||
|
||||
_waitingToClose: false,
|
||||
closing: function closing() {
|
||||
// If we are already waiting for the close prompt, don't show another
|
||||
if (this._waitingToClose)
|
||||
return false;
|
||||
|
||||
// Prompt if we have multiple tabs before closing window
|
||||
let numTabs = this._tabs.length;
|
||||
if (numTabs > 1) {
|
||||
let shouldPrompt = Services.prefs.getBoolPref("browser.tabs.warnOnClose");
|
||||
if (shouldPrompt) {
|
||||
let prompt = Services.prompt;
|
||||
|
||||
// Default to true: if it were false, we wouldn't get this far
|
||||
let warnOnClose = { value: true };
|
||||
|
||||
let messageBase = Strings.browser.GetStringFromName("tabs.closeWarning");
|
||||
let message = PluralForm.get(numTabs, messageBase).replace("#1", numTabs);
|
||||
|
||||
let title = Strings.browser.GetStringFromName("tabs.closeWarningTitle");
|
||||
let closeText = Strings.browser.GetStringFromName("tabs.closeButton");
|
||||
let checkText = Strings.browser.GetStringFromName("tabs.closeWarningPromptMe");
|
||||
let buttons = (prompt.BUTTON_TITLE_IS_STRING * prompt.BUTTON_POS_0) +
|
||||
(prompt.BUTTON_TITLE_CANCEL * prompt.BUTTON_POS_1);
|
||||
|
||||
this._waitingToClose = true;
|
||||
let pressed = prompt.confirmEx(window, title, message, buttons, closeText, null, null, checkText, warnOnClose);
|
||||
this._waitingToClose = false;
|
||||
|
||||
// Don't set the pref unless they press OK and it's false
|
||||
let reallyClose = (pressed == 0);
|
||||
if (reallyClose && !warnOnClose.value)
|
||||
Services.prefs.setBoolPref("browser.tabs.warnOnClose", false);
|
||||
|
||||
// If we don't want to close, return now. If we are closing, continue with other housekeeping.
|
||||
if (!reallyClose)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out if there's at least one other browser window around.
|
||||
let lastBrowser = true;
|
||||
let e = Services.wm.getEnumerator("navigator:browser");
|
||||
|
|
|
@ -218,7 +218,7 @@ Prompt.prototype = {
|
|||
|
||||
if (aCheck && aCheck.msg) {
|
||||
aDoc.getElementById("prompt-" + aType + "-checkbox").checked = aCheck.value;
|
||||
this.setLabelForNode(aDoc.getElementById("prompt-" + aType + "-checkbox-label"), aCheck.msg);
|
||||
this.setLabelForNode(aDoc.getElementById("prompt-" + aType + "-checkbox"), aCheck.msg);
|
||||
aDoc.getElementById("prompt-" + aType + "-checkbox").removeAttribute("collapsed");
|
||||
}
|
||||
},
|
||||
|
|
|
@ -73,16 +73,6 @@ offlineApps.wantsTo=%S wants to store data on your device for offline use.
|
|||
indexedDBQuota.allow=Allow
|
||||
indexedDBQuota.wantsTo=%S wants to store a lot of data on your device for offline use.
|
||||
|
||||
# Closing Tabs
|
||||
tabs.closeWarningTitle=Confirm close
|
||||
|
||||
# LOCALIZATION NOTE (tabs.closeWarning): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of tabs (must be greater than 1)
|
||||
tabs.closeWarning=NOT USED;You are about to close #1 tabs. Continue?
|
||||
|
||||
tabs.closeButton=Close tabs
|
||||
tabs.closeWarningPromptMe=Warn me when I attempt to close multiple tabs
|
||||
tabs.emptyTabTitle=New Tab
|
||||
|
||||
# Open Search
|
||||
|
|
|
@ -67,7 +67,6 @@ pref("browser.chromeURL", "chrome://browser/content/");
|
|||
// When true, always show the tab strip and use desktop-style tabs (no thumbnails)
|
||||
pref("browser.tabs.tabsOnly", false);
|
||||
|
||||
pref("browser.tabs.warnOnClose", true);
|
||||
pref("browser.tabs.remote", false);
|
||||
|
||||
// Telemetry
|
||||
|
|
|
@ -1355,6 +1355,11 @@ public:
|
|||
*/
|
||||
static bool IsSystemPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
/**
|
||||
* Gets the system principal from the security manager.
|
||||
*/
|
||||
static nsIPrincipal* GetSystemPrincipal();
|
||||
|
||||
/**
|
||||
* *aResourcePrincipal is a principal describing who may access the contents
|
||||
* of a resource. The resource can only be consumed by a principal that
|
||||
|
|
|
@ -77,6 +77,7 @@ class nsSmallVoidArray;
|
|||
class nsDOMCaretPosition;
|
||||
class nsViewportInfo;
|
||||
class nsDOMEvent;
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
@ -110,8 +111,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
|
|||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x699e0649, 0x55f2, 0x47f1, \
|
||||
{ 0x93, 0x38, 0xcd, 0x67, 0xf3, 0x2b, 0x04, 0xe9 } }
|
||||
{ 0x8f33bc23, 0x5625, 0x448a, \
|
||||
{ 0xb3, 0x38, 0xfe, 0x88, 0x16, 0xe, 0xb3, 0xdb } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -806,7 +807,8 @@ public:
|
|||
* document is truly gone. Use this object when you're trying to find a
|
||||
* content wrapper in XPConnect.
|
||||
*/
|
||||
virtual nsIScriptGlobalObject* GetScopeObject() const = 0;
|
||||
virtual nsIGlobalObject* GetScopeObject() const = 0;
|
||||
virtual void SetScopeObject(nsIGlobalObject* aGlobal) = 0;
|
||||
|
||||
/**
|
||||
* Return the window containing the document (the outer window).
|
||||
|
@ -1908,7 +1910,7 @@ public:
|
|||
}
|
||||
|
||||
// WebIDL API
|
||||
nsIScriptGlobalObject* GetParentObject() const
|
||||
nsIGlobalObject* GetParentObject() const
|
||||
{
|
||||
return GetScopeObject();
|
||||
}
|
||||
|
@ -2312,6 +2314,8 @@ protected:
|
|||
// document was created entirely in memory
|
||||
bool mHaveInputEncoding;
|
||||
|
||||
bool mHasHadDefaultView;
|
||||
|
||||
// The document's script global object, the object from which the
|
||||
// document can get its script context and scope. This is the
|
||||
// *inner* window object.
|
||||
|
@ -2511,7 +2515,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
|||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aLoadedAsData,
|
||||
nsIScriptGlobalObject* aEventObject,
|
||||
nsIGlobalObject* aEventObject,
|
||||
DocumentFlavor aFlavor);
|
||||
|
||||
// This is used only for xbl documents created from the startup cache.
|
||||
|
|
|
@ -12,7 +12,7 @@ interface nsIPrincipal;
|
|||
interface nsIScriptContext;
|
||||
interface nsIURI;
|
||||
interface nsIVariant;
|
||||
interface nsPIDOMWindow;
|
||||
interface nsIGlobalObject;
|
||||
interface nsIInputStream;
|
||||
interface nsIDOMBlob;
|
||||
|
||||
|
@ -79,7 +79,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
|
|||
* you're aware of all the security implications. And then think twice about
|
||||
* it.
|
||||
*/
|
||||
[scriptable, uuid(cd31a34e-71b5-4bea-8366-c926de9d3d62)]
|
||||
[scriptable, uuid(977f1406-416a-40ac-ab89-ccd7ca0622ea)]
|
||||
interface nsIXMLHttpRequest : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -301,13 +301,16 @@ interface nsIXMLHttpRequest : nsISupports
|
|||
* null.
|
||||
* @param scriptContext The script context to use for the request. May be
|
||||
* null.
|
||||
* @param ownerWindow The associated window for the request. May be null.
|
||||
* @param globalObject The associated global for the request. Can be the
|
||||
* outer window, a sandbox, or a backstage pass.
|
||||
* May be null, but then the request cannot create a
|
||||
* document.
|
||||
* @param baseURI The base URI to use when resolving relative URIs. May be
|
||||
* null.
|
||||
*/
|
||||
[noscript] void init(in nsIPrincipal principal,
|
||||
in nsIScriptContext scriptContext,
|
||||
in nsPIDOMWindow ownerWindow,
|
||||
in nsIGlobalObject globalObject,
|
||||
in nsIURI baseURI);
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,7 +114,7 @@ DOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
|
||||
nsCOMPtr<nsIGlobalObject> scriptHandlingObject =
|
||||
do_QueryReferent(mScriptObject);
|
||||
|
||||
NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
|
||||
|
@ -182,7 +182,7 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
|
||||
nsCOMPtr<nsIGlobalObject> scriptHandlingObject =
|
||||
do_QueryReferent(mScriptObject);
|
||||
|
||||
NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
|
||||
|
@ -211,20 +211,22 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
|||
rv = root->AppendChildTo(head, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContent> title;
|
||||
rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr, kNameSpaceID_XHTML,
|
||||
getter_AddRefs(title));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = head->AppendChildTo(title, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!DOMStringIsNull(aTitle)) {
|
||||
nsCOMPtr<nsIContent> title;
|
||||
rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr,
|
||||
kNameSpaceID_XHTML, getter_AddRefs(title));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = head->AppendChildTo(title, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContent> titleText;
|
||||
rv = NS_NewTextNode(getter_AddRefs(titleText), doc->NodeInfoManager());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = titleText->SetText(aTitle, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = title->AppendChildTo(titleText, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIContent> titleText;
|
||||
rv = NS_NewTextNode(getter_AddRefs(titleText), doc->NodeInfoManager());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = titleText->SetText(aTitle, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = title->AppendChildTo(titleText, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> body;
|
||||
rv = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML,
|
||||
|
@ -241,12 +243,14 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
|||
}
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
||||
DOMImplementation::CreateHTMLDocument(const Optional<nsAString>& aTitle,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
aRv = CreateHTMLDocument(aTitle, getter_AddRefs(document),
|
||||
aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value()
|
||||
: NullString(),
|
||||
getter_AddRefs(document),
|
||||
getter_AddRefs(domDocument));
|
||||
return document.forget();
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class DOMImplementation MOZ_FINAL : public nsIDOMDOMImplementation
|
|||
{
|
||||
public:
|
||||
DOMImplementation(nsIDocument* aOwner,
|
||||
nsIScriptGlobalObject* aScriptObject,
|
||||
nsIGlobalObject* aScriptObject,
|
||||
nsIURI* aDocumentURI,
|
||||
nsIURI* aBaseURI)
|
||||
: mOwner(aOwner)
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
CreateHTMLDocument(const nsAString& aTitle, ErrorResult& aRv);
|
||||
CreateHTMLDocument(const Optional<nsAString>& aTitle, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
nsresult CreateDocument(const nsAString& aNamespaceURI,
|
||||
|
|
|
@ -1666,7 +1666,7 @@ nsContentUtils::InProlog(nsINode *aNode)
|
|||
JSContext *
|
||||
nsContentUtils::GetContextFromDocument(nsIDocument *aDocument)
|
||||
{
|
||||
nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aDocument->GetScopeObject());
|
||||
if (!sgo) {
|
||||
// No script global, no context.
|
||||
return nullptr;
|
||||
|
@ -4698,6 +4698,15 @@ nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
|
|||
return NS_SUCCEEDED(rv) && isSystem;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
nsContentUtils::GetSystemPrincipal()
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> sysPrin;
|
||||
nsresult rv = sSecurityManager->GetSystemPrincipal(getter_AddRefs(sysPrin));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && sysPrin);
|
||||
return sysPrin;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::CombineResourcePrincipals(nsCOMPtr<nsIPrincipal>* aResourcePrincipal,
|
||||
nsIPrincipal* aExtraPrincipal)
|
||||
|
|
|
@ -4020,13 +4020,22 @@ nsDocument::GetScriptGlobalObject() const
|
|||
return mScriptGlobalObject;
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject*
|
||||
nsIGlobalObject*
|
||||
nsDocument::GetScopeObject() const
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> scope(do_QueryReferent(mScopeObject));
|
||||
nsCOMPtr<nsIGlobalObject> scope(do_QueryReferent(mScopeObject));
|
||||
return scope;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
|
||||
{
|
||||
mScopeObject = do_GetWeakReference(aGlobal);
|
||||
if (aGlobal) {
|
||||
mHasHadScriptHandlingObject = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyActivityChanged(nsIContent *aContent, void *aUnused)
|
||||
{
|
||||
|
@ -4089,12 +4098,11 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
|||
mScriptGlobalObject = aScriptGlobalObject;
|
||||
|
||||
if (aScriptGlobalObject) {
|
||||
mScriptObject = nullptr;
|
||||
mHasHadScriptHandlingObject = true;
|
||||
mHasHadDefaultView = true;
|
||||
// Go back to using the docshell for the layout history state
|
||||
mLayoutHistoryState = nullptr;
|
||||
mScopeObject = do_GetWeakReference(aScriptGlobalObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!mWillReparent) {
|
||||
// We really shouldn't have a wrapper here but if we do we need to make sure
|
||||
|
@ -4144,9 +4152,12 @@ nsDocument::GetScriptHandlingObjectInternal() const
|
|||
{
|
||||
MOZ_ASSERT(!mScriptGlobalObject,
|
||||
"Do not call this when mScriptGlobalObject is set!");
|
||||
if (mHasHadDefaultView) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
|
||||
do_QueryReferent(mScriptObject);
|
||||
do_QueryReferent(mScopeObject);
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptHandlingObject);
|
||||
if (win) {
|
||||
NS_ASSERTION(win->IsInnerWindow(), "Should have inner window here!");
|
||||
|
@ -4166,9 +4177,10 @@ nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
|
|||
"Wrong script object!");
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aScriptObject);
|
||||
NS_ASSERTION(!win || win->IsInnerWindow(), "Should have inner window here!");
|
||||
mScopeObject = mScriptObject = do_GetWeakReference(aScriptObject);
|
||||
if (aScriptObject) {
|
||||
mScopeObject = do_GetWeakReference(aScriptObject);
|
||||
mHasHadScriptHandlingObject = true;
|
||||
mHasHadDefaultView = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4635,7 +4647,8 @@ nsDocument::GetImplementation(ErrorResult& rv)
|
|||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
mDOMImplementation = new DOMImplementation(this, scriptObject, uri, uri);
|
||||
mDOMImplementation = new DOMImplementation(this,
|
||||
scriptObject ? scriptObject : GetScopeObject(), uri, uri);
|
||||
}
|
||||
|
||||
return mDOMImplementation;
|
||||
|
@ -5038,7 +5051,7 @@ nsDocument::Register(JSContext* aCx, const nsAString& aName,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject* sgo = GetScopeObject();
|
||||
nsIGlobalObject* sgo = GetScopeObject();
|
||||
if (!sgo) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
|
@ -6513,7 +6526,8 @@ GetContextAndScope(nsIDocument* aOldDocument, nsIDocument* aNewDocument,
|
|||
JSObject* newScope = aNewDocument->GetWrapper();
|
||||
JSObject* global;
|
||||
if (!newScope) {
|
||||
nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
|
||||
nsIGlobalObject *newSGO = aNewDocument->GetScopeObject();
|
||||
|
||||
if (!newSGO || !(global = newSGO->GetGlobalJSObject())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -8305,8 +8319,11 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
|
|||
nsIScriptGlobalObject* scriptObject =
|
||||
GetScriptHandlingObject(hasHadScriptObject);
|
||||
NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
|
||||
clone->SetScriptHandlingObject(scriptObject);
|
||||
|
||||
if (scriptObject) {
|
||||
clone->SetScriptHandlingObject(scriptObject);
|
||||
} else {
|
||||
clone->SetScopeObject(GetScopeObject());
|
||||
}
|
||||
// Make the clone a data document
|
||||
clone->SetLoadedAsData(true);
|
||||
|
||||
|
|
|
@ -637,8 +637,8 @@ public:
|
|||
|
||||
virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject);
|
||||
|
||||
virtual nsIScriptGlobalObject* GetScopeObject() const;
|
||||
|
||||
virtual nsIGlobalObject* GetScopeObject() const;
|
||||
void SetScopeObject(nsIGlobalObject* aGlobal);
|
||||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
|
@ -1180,11 +1180,6 @@ protected:
|
|||
// Array of observers
|
||||
nsTObserverArray<nsIDocumentObserver*> mObservers;
|
||||
|
||||
// If document is created for example using
|
||||
// document.implementation.createDocument(...), mScriptObject points to
|
||||
// the script global object of the original document.
|
||||
nsWeakPtr mScriptObject;
|
||||
|
||||
// Weak reference to the scope object (aka the script global object)
|
||||
// that, unlike mScriptGlobalObject, is never unset once set. This
|
||||
// is a weak reference to avoid leaks due to circular references.
|
||||
|
|
|
@ -167,6 +167,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper,
|
||||
public nsFrameScriptExecutor,
|
||||
public nsIInProcessContentFrameMessageManager,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIScriptContextPrincipal,
|
||||
public nsIGlobalObject,
|
||||
public nsSupportsWeakReference,
|
||||
public mozilla::dom::ipc::MessageManagerCallback
|
||||
{
|
||||
public:
|
||||
|
@ -113,6 +116,17 @@ public:
|
|||
}
|
||||
|
||||
void DelayedDisconnect();
|
||||
|
||||
virtual JSObject* GetGlobalJSObject() {
|
||||
if (!mGlobal) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* global;
|
||||
mGlobal->GetJSObject(&global);
|
||||
|
||||
return global;
|
||||
}
|
||||
protected:
|
||||
nsresult Init();
|
||||
nsresult InitTabChildGlobal();
|
||||
|
|
|
@ -2609,7 +2609,7 @@ nsObjectLoadingContent::NotifyContentObjectWrapper()
|
|||
if (!doc)
|
||||
return;
|
||||
|
||||
nsIScriptGlobalObject *sgo = doc->GetScopeObject();
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(doc->GetScopeObject());
|
||||
if (!sgo)
|
||||
return;
|
||||
|
||||
|
|
|
@ -342,7 +342,11 @@ nsXMLHttpRequest::Init()
|
|||
secMan->GetSystemPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
}
|
||||
NS_ENSURE_STATE(subjectPrincipal);
|
||||
Construct(subjectPrincipal, nullptr);
|
||||
|
||||
// Instead of grabbing some random global from the context stack,
|
||||
// let's use the default one (junk drawer) for now.
|
||||
// We should move away from this Init...
|
||||
Construct(subjectPrincipal, xpc::GetNativeForGlobal(xpc::GetJunkScope()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -352,15 +356,21 @@ nsXMLHttpRequest::Init()
|
|||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
|
||||
nsIScriptContext* aScriptContext,
|
||||
nsPIDOMWindow* aOwnerWindow,
|
||||
nsIGlobalObject* aGlobalObject,
|
||||
nsIURI* aBaseURI)
|
||||
{
|
||||
NS_ASSERTION(!aOwnerWindow || aOwnerWindow->IsOuterWindow(),
|
||||
"Expecting an outer window here!");
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
Construct(aPrincipal,
|
||||
aOwnerWindow ? aOwnerWindow->GetCurrentInnerWindow() : nullptr,
|
||||
aBaseURI);
|
||||
|
||||
if (nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobalObject)) {
|
||||
if (win->IsOuterWindow()) {
|
||||
// Must be bound to inner window, innerize if necessary.
|
||||
nsCOMPtr<nsIGlobalObject> inner = do_QueryInterface(
|
||||
win->GetCurrentInnerWindow());
|
||||
aGlobalObject = inner.get();
|
||||
}
|
||||
}
|
||||
|
||||
Construct(aPrincipal, aGlobalObject, aBaseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1990,8 +2000,8 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
// principal, so use mPrincipal when creating the document, then reset the
|
||||
// principal.
|
||||
const nsAString& emptyStr = EmptyString();
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
nsCOMPtr<nsIDOMDocument> responseDoc;
|
||||
nsIGlobalObject* global = nsDOMEventTargetHelper::GetParentObject();
|
||||
rv = NS_NewDOMDocument(getter_AddRefs(responseDoc),
|
||||
emptyStr, emptyStr, nullptr, docURI,
|
||||
baseURI, mPrincipal, true, global,
|
||||
|
|
|
@ -147,16 +147,16 @@ public:
|
|||
const mozilla::dom::MozXMLHttpRequestParameters& aParams,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.Get());
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> principal =
|
||||
do_QueryInterface(aGlobal.Get());
|
||||
if (!window || ! principal) {
|
||||
if (!global || ! principal) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<nsXMLHttpRequest> req = new nsXMLHttpRequest();
|
||||
req->Construct(principal->GetPrincipal(), window);
|
||||
req->Construct(principal->GetPrincipal(), global);
|
||||
req->InitParameters(aParams.mMozAnon, aParams.mMozSystem);
|
||||
return req.forget();
|
||||
}
|
||||
|
@ -178,13 +178,14 @@ public:
|
|||
}
|
||||
|
||||
void Construct(nsIPrincipal* aPrincipal,
|
||||
nsPIDOMWindow* aOwnerWindow,
|
||||
nsIGlobalObject* aGlobalObject,
|
||||
nsIURI* aBaseURI = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT_IF(aOwnerWindow, aOwnerWindow->IsInnerWindow());
|
||||
MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(
|
||||
aGlobalObject), win->IsInnerWindow());
|
||||
mPrincipal = aPrincipal;
|
||||
BindToOwner(aOwnerWindow);
|
||||
BindToOwner(aGlobalObject);
|
||||
mBaseURI = aBaseURI;
|
||||
}
|
||||
|
||||
|
@ -458,6 +459,11 @@ public:
|
|||
// This is called by the factory constructor.
|
||||
nsresult Init();
|
||||
|
||||
nsresult init(nsIPrincipal* principal,
|
||||
nsIScriptContext* scriptContext,
|
||||
nsPIDOMWindow* globalObject,
|
||||
nsIURI* baseURI);
|
||||
|
||||
void SetRequestObserver(nsIRequestObserver* aObserver);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
|
||||
|
|
|
@ -26,8 +26,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
|
|||
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
|
||||
char name[512];
|
||||
nsAutoString uri;
|
||||
if (tmp->mOwner && tmp->mOwner->GetExtantDocument()) {
|
||||
tmp->mOwner->GetExtantDocument()->GetDocumentURI(uri);
|
||||
if (tmp->mOwnerWindow && tmp->mOwnerWindow->GetExtantDocument()) {
|
||||
tmp->mOwnerWindow->GetExtantDocument()->GetDocumentURI(uri);
|
||||
}
|
||||
PR_snprintf(name, sizeof(name), "nsDOMEventTargetHelper %s",
|
||||
NS_ConvertUTF16toUTF8(uri).get());
|
||||
|
@ -77,8 +77,8 @@ NS_IMPL_DOMTARGET_DEFAULTS(nsDOMEventTargetHelper)
|
|||
|
||||
nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
|
||||
{
|
||||
if (mOwner) {
|
||||
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
||||
if (nsPIDOMWindow* owner = GetOwner()) {
|
||||
static_cast<nsGlobalWindow*>(owner)->RemoveEventTargetObject(this);
|
||||
}
|
||||
if (mListenerManager) {
|
||||
mListenerManager->Disconnect();
|
||||
|
@ -89,32 +89,51 @@ nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
|
|||
void
|
||||
nsDOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
|
||||
{
|
||||
if (mOwner) {
|
||||
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
||||
mOwner = nullptr;
|
||||
mHasOrHasHadOwner = false;
|
||||
nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOwner);
|
||||
BindToOwner(glob);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
|
||||
{
|
||||
if (mParentObject) {
|
||||
if (mOwnerWindow) {
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->RemoveEventTargetObject(this);
|
||||
mOwnerWindow = nullptr;
|
||||
}
|
||||
mParentObject = nullptr;
|
||||
mHasOrHasHadOwnerWindow = false;
|
||||
}
|
||||
if (aOwner) {
|
||||
mOwner = aOwner;
|
||||
mHasOrHasHadOwner = true;
|
||||
static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
|
||||
mParentObject = aOwner;
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOwner)).get();
|
||||
if (mOwnerWindow) {
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMEventTargetHelper::BindToOwner(nsDOMEventTargetHelper* aOther)
|
||||
{
|
||||
if (mOwner) {
|
||||
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
||||
mOwner = nullptr;
|
||||
mHasOrHasHadOwner = false;
|
||||
if (mOwnerWindow) {
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->RemoveEventTargetObject(this);
|
||||
mOwnerWindow = nullptr;
|
||||
mParentObject = nullptr;
|
||||
mHasOrHasHadOwnerWindow = false;
|
||||
}
|
||||
if (aOther) {
|
||||
mHasOrHasHadOwner = aOther->HasOrHasHadOwner();
|
||||
if (aOther->GetOwner()) {
|
||||
mOwner = aOther->GetOwner();
|
||||
mHasOrHasHadOwner = true;
|
||||
static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
|
||||
mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
|
||||
if (aOther->GetParentObject()) {
|
||||
mParentObject = aOther->GetParentObject();
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(mParentObject)).get();
|
||||
if (mOwnerWindow) {
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +141,8 @@ nsDOMEventTargetHelper::BindToOwner(nsDOMEventTargetHelper* aOther)
|
|||
void
|
||||
nsDOMEventTargetHelper::DisconnectFromOwner()
|
||||
{
|
||||
mOwner = nullptr;
|
||||
mOwnerWindow = nullptr;
|
||||
mParentObject = nullptr;
|
||||
// Event listeners can't be handled anymore, so we can release them here.
|
||||
if (mListenerManager) {
|
||||
mListenerManager->Disconnect();
|
||||
|
@ -308,8 +328,9 @@ nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
|
|||
if (NS_FAILED(*aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
return mOwner ? static_cast<nsGlobalWindow*>(mOwner)->GetContextInternal()
|
||||
: nullptr;
|
||||
nsPIDOMWindow* owner = GetOwner();
|
||||
return owner ? static_cast<nsGlobalWindow*>(owner)->GetContextInternal()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -25,7 +25,7 @@ class nsDOMEvent;
|
|||
class nsDOMEventTargetHelper : public mozilla::dom::EventTarget
|
||||
{
|
||||
public:
|
||||
nsDOMEventTargetHelper() : mOwner(nullptr), mHasOrHasHadOwner(false) {}
|
||||
nsDOMEventTargetHelper() : mParentObject(nullptr), mOwnerWindow(nullptr), mHasOrHasHadOwnerWindow(false) {}
|
||||
virtual ~nsDOMEventTargetHelper();
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsDOMEventTargetHelper)
|
||||
|
@ -36,10 +36,9 @@ public:
|
|||
|
||||
void GetParentObject(nsIScriptGlobalObject **aParentObject)
|
||||
{
|
||||
if (mOwner) {
|
||||
CallQueryInterface(mOwner, aParentObject);
|
||||
}
|
||||
else {
|
||||
if (mParentObject) {
|
||||
CallQueryInterface(mParentObject, aParentObject);
|
||||
} else {
|
||||
*aParentObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -90,22 +89,24 @@ public:
|
|||
|
||||
nsresult CheckInnerWindowCorrectness()
|
||||
{
|
||||
NS_ENSURE_STATE(!mHasOrHasHadOwner || mOwner);
|
||||
if (mOwner) {
|
||||
NS_ASSERTION(mOwner->IsInnerWindow(), "Should have inner window here!\n");
|
||||
nsPIDOMWindow* outer = mOwner->GetOuterWindow();
|
||||
if (!outer || outer->GetCurrentInnerWindow() != mOwner) {
|
||||
NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
|
||||
if (mOwnerWindow) {
|
||||
NS_ASSERTION(mOwnerWindow->IsInnerWindow(), "Should have inner window here!\n");
|
||||
nsPIDOMWindow* outer = mOwnerWindow->GetOuterWindow();
|
||||
if (!outer || outer->GetCurrentInnerWindow() != mOwnerWindow) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPIDOMWindow* GetOwner() const { return mOwnerWindow; }
|
||||
void BindToOwner(nsIGlobalObject* aOwner);
|
||||
void BindToOwner(nsPIDOMWindow* aOwner);
|
||||
void BindToOwner(nsDOMEventTargetHelper* aOther);
|
||||
virtual void DisconnectFromOwner();
|
||||
nsPIDOMWindow* GetOwner() const { return mOwner; }
|
||||
bool HasOrHasHadOwner() { return mHasOrHasHadOwner; }
|
||||
nsIGlobalObject* GetParentObject() const { return mParentObject; }
|
||||
bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
|
||||
protected:
|
||||
nsRefPtr<nsEventListenerManager> mListenerManager;
|
||||
// Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
|
||||
|
@ -113,9 +114,12 @@ protected:
|
|||
// Make |event| trusted and dispatch |aEvent| to |this|.
|
||||
nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent);
|
||||
private:
|
||||
// These may be null (native callers or xpcshell).
|
||||
nsPIDOMWindow* mOwner; // Inner window.
|
||||
bool mHasOrHasHadOwner;
|
||||
// Inner window or sandbox.
|
||||
nsIGlobalObject* mParentObject;
|
||||
// mParentObject pre QI-ed and cached
|
||||
// (it is needed for off main thread access)
|
||||
nsPIDOMWindow* mOwnerWindow;
|
||||
bool mHasOrHasHadOwnerWindow;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMEventTargetHelper,
|
||||
|
|
|
@ -628,7 +628,7 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
|
|||
|
||||
// We want to allow compiling an event handler even in an unloaded
|
||||
// document, so use GetScopeObject here, not GetScriptHandlingObject.
|
||||
global = doc->GetScopeObject();
|
||||
global = do_QueryInterface(doc->GetScopeObject());
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
|
||||
if (win) {
|
||||
|
|
|
@ -249,22 +249,7 @@ public:
|
|||
|
||||
// If the requested time is before all of the existing events
|
||||
if (!previous) {
|
||||
switch (next->mType) {
|
||||
case AudioTimelineEvent::SetValue:
|
||||
case AudioTimelineEvent::SetTarget:
|
||||
// The requested time is before the first event
|
||||
return mValue;
|
||||
case AudioTimelineEvent::LinearRamp:
|
||||
// Use t=0 as T0 and v=defaultValue as V0
|
||||
return LinearInterpolate(0.0, mValue, next->template Time<TimeType>(), next->mValue, aTime);
|
||||
case AudioTimelineEvent::ExponentialRamp:
|
||||
// Use t=0 as T0 and v=defaultValue as V0
|
||||
return ExponentialInterpolate(0.0, mValue, next->template Time<TimeType>(), next->mValue, aTime);
|
||||
case AudioTimelineEvent::SetValueCurve:
|
||||
// TODO: implement
|
||||
return 0.0f;
|
||||
}
|
||||
MOZ_ASSERT(false, "unreached");
|
||||
return mValue;
|
||||
}
|
||||
|
||||
// SetTarget nodes can be handled no matter what their next node is (if they have one)
|
||||
|
|
|
@ -191,9 +191,6 @@ AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
|
|||
continue;
|
||||
}
|
||||
AudioChunk* chunk = &a->mLastChunk;
|
||||
// XXX when we implement DelayNode, this will no longer be true and we'll
|
||||
// need to treat a null chunk (when the DelayNode hasn't had a chance
|
||||
// to produce data yet) as silence here.
|
||||
MOZ_ASSERT(chunk);
|
||||
if (chunk->IsNull()) {
|
||||
continue;
|
||||
|
|
|
@ -41,6 +41,14 @@ static Mutex* gAudioPrefsLock = nullptr;
|
|||
static double gVolumeScale;
|
||||
static uint32_t gCubebLatency;
|
||||
|
||||
/**
|
||||
* When MOZ_DUMP_AUDIO is set in the environment (to anything),
|
||||
* we'll drop a series of files in the current working directory named
|
||||
* dumped-audio-<nnn>.wav, one per nsBufferedAudioStream created, containing
|
||||
* the audio for the stream including any skips due to underruns.
|
||||
*/
|
||||
static int gDumpedAudioCount = 0;
|
||||
|
||||
static int PrefChanged(const char* aPref, void* aClosure)
|
||||
{
|
||||
if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) {
|
||||
|
@ -355,6 +363,9 @@ private:
|
|||
// than are available in mBuffer.
|
||||
uint64_t mLostFrames;
|
||||
|
||||
// Output file for dumping audio
|
||||
FILE* mDumpFile;
|
||||
|
||||
// Temporary audio buffer. Filled by Write() and consumed by
|
||||
// DataCallback(). Once mBuffer is full, Write() blocks until sufficient
|
||||
// space becomes available in mBuffer. mBuffer is sized in bytes, not
|
||||
|
@ -405,16 +416,88 @@ AudioStream* AudioStream::AllocateStream()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static void SetUint16LE(PRUint8* aDest, PRUint16 aValue)
|
||||
{
|
||||
aDest[0] = aValue & 0xFF;
|
||||
aDest[1] = aValue >> 8;
|
||||
}
|
||||
|
||||
static void SetUint32LE(PRUint8* aDest, PRUint32 aValue)
|
||||
{
|
||||
SetUint16LE(aDest, aValue & 0xFFFF);
|
||||
SetUint16LE(aDest + 2, aValue >> 16);
|
||||
}
|
||||
|
||||
static FILE*
|
||||
OpenDumpFile(AudioStream* aStream)
|
||||
{
|
||||
if (!getenv("MOZ_DUMP_AUDIO"))
|
||||
return nullptr;
|
||||
char buf[100];
|
||||
sprintf(buf, "dumped-audio-%d.wav", gDumpedAudioCount);
|
||||
FILE* f = fopen(buf, "wb");
|
||||
if (!f)
|
||||
return nullptr;
|
||||
++gDumpedAudioCount;
|
||||
|
||||
PRUint8 header[] = {
|
||||
// RIFF header
|
||||
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
|
||||
// fmt chunk. We always write 16-bit samples.
|
||||
0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x00,
|
||||
// data chunk
|
||||
0x64, 0x61, 0x74, 0x61, 0xFE, 0xFF, 0xFF, 0x7F
|
||||
};
|
||||
static const int CHANNEL_OFFSET = 22;
|
||||
static const int SAMPLE_RATE_OFFSET = 24;
|
||||
static const int BLOCK_ALIGN_OFFSET = 32;
|
||||
SetUint16LE(header + CHANNEL_OFFSET, aStream->GetChannels());
|
||||
SetUint32LE(header + SAMPLE_RATE_OFFSET, aStream->GetRate());
|
||||
SetUint16LE(header + BLOCK_ALIGN_OFFSET, aStream->GetChannels()*2);
|
||||
fwrite(header, sizeof(header), 1, f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static void
|
||||
WriteDumpFile(FILE* aDumpFile, AudioStream* aStream, PRUint32 aFrames,
|
||||
void* aBuffer)
|
||||
{
|
||||
if (!aDumpFile)
|
||||
return;
|
||||
|
||||
PRUint32 samples = aStream->GetChannels()*aFrames;
|
||||
if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
|
||||
fwrite(aBuffer, 2, samples, aDumpFile);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_FLOAT32, "bad format");
|
||||
nsAutoTArray<PRUint8, 1024*2> buf;
|
||||
buf.SetLength(samples*2);
|
||||
float* input = static_cast<float*>(aBuffer);
|
||||
PRUint8* output = buf.Elements();
|
||||
for (PRUint32 i = 0; i < samples; ++i) {
|
||||
SetUint16LE(output + i*2, PRInt16(input[i]*32767.0f));
|
||||
}
|
||||
fwrite(output, 2, samples, aDumpFile);
|
||||
fflush(aDumpFile);
|
||||
}
|
||||
|
||||
#if defined(MOZ_CUBEB)
|
||||
BufferedAudioStream::BufferedAudioStream()
|
||||
: mMonitor("BufferedAudioStream"), mLostFrames(0), mVolume(1.0),
|
||||
mBytesPerFrame(0), mState(INITIALIZED)
|
||||
: mMonitor("BufferedAudioStream"), mLostFrames(0), mDumpFile(nullptr),
|
||||
mVolume(1.0), mBytesPerFrame(0), mState(INITIALIZED)
|
||||
{
|
||||
}
|
||||
|
||||
BufferedAudioStream::~BufferedAudioStream()
|
||||
{
|
||||
Shutdown();
|
||||
if (mDumpFile) {
|
||||
fclose(mDumpFile);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -437,6 +520,8 @@ BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
|||
mInRate = mOutRate = aRate;
|
||||
mChannels = aNumChannels;
|
||||
|
||||
mDumpFile = OpenDumpFile(this);
|
||||
|
||||
cubeb_stream_params params;
|
||||
params.rate = aRate;
|
||||
params.channels = aNumChannels;
|
||||
|
@ -777,10 +862,18 @@ BufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
|
|||
if (mState != DRAINING) {
|
||||
uint8_t* rpos = static_cast<uint8_t*>(aBuffer) + FramesToBytes(aFrames - underrunFrames);
|
||||
memset(rpos, 0, FramesToBytes(underrunFrames));
|
||||
#ifdef PR_LOGGING
|
||||
if (underrunFrames) {
|
||||
PR_LOG(gAudioStreamLog, PR_LOG_WARNING,
|
||||
("AudioStream %p lost %d frames", this, underrunFrames));
|
||||
}
|
||||
#endif
|
||||
mLostFrames += underrunFrames;
|
||||
servicedFrames += underrunFrames;
|
||||
}
|
||||
|
||||
WriteDumpFile(mDumpFile, this, aFrames, aBuffer);
|
||||
|
||||
mAudioClock.UpdateWritePosition(servicedFrames);
|
||||
return servicedFrames;
|
||||
}
|
||||
|
|
|
@ -253,10 +253,6 @@ public:
|
|||
* Produce data for all streams >= aStreamIndex for the given time interval.
|
||||
* Advances block by block, each iteration producing data for all streams
|
||||
* for a single block.
|
||||
* This is needed if there are WebAudio delay nodes, whose output for a block
|
||||
* may depend on the output of any other node (including itself) for the
|
||||
* previous block. This is probably also more performant due to better memory
|
||||
* locality.
|
||||
* This is called whenever we have an AudioNodeStream in the graph.
|
||||
*/
|
||||
void ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include "DelayNode.h"
|
||||
#include "mozilla/dom/DelayNodeBinding.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioDestinationNode.h"
|
||||
#include "WebAudioUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -19,10 +23,191 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
|
|||
NS_IMPL_ADDREF_INHERITED(DelayNode, AudioNode)
|
||||
NS_IMPL_RELEASE_INHERITED(DelayNode, AudioNode)
|
||||
|
||||
class DelayNodeEngine : public AudioNodeEngine
|
||||
{
|
||||
public:
|
||||
explicit DelayNodeEngine(AudioDestinationNode* aDestination)
|
||||
: mSource(nullptr)
|
||||
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
|
||||
// Keep the default value in sync with the default value in DelayNode::DelayNode.
|
||||
, mDelay(0.f)
|
||||
, mMaxDelay(0.)
|
||||
, mWriteIndex(0)
|
||||
, mCurrentDelayTime(0.)
|
||||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
DELAY,
|
||||
MAX_DELAY
|
||||
};
|
||||
void SetTimelineParameter(uint32_t aIndex, const AudioParamTimeline& aValue) MOZ_OVERRIDE
|
||||
{
|
||||
switch (aIndex) {
|
||||
case DELAY:
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
mDelay = aValue;
|
||||
WebAudioUtils::ConvertAudioParamToTicks(mDelay, mSource, mDestination);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Bad DelayNodeEngine TimelineParameter");
|
||||
}
|
||||
}
|
||||
void SetDoubleParameter(uint32_t aIndex, double aValue) MOZ_OVERRIDE
|
||||
{
|
||||
switch (aIndex) {
|
||||
case MAX_DELAY: mMaxDelay = aValue; break;
|
||||
default:
|
||||
NS_ERROR("Bad DelayNodeEngine DoubleParameter");
|
||||
}
|
||||
}
|
||||
|
||||
bool EnsureBuffer(uint32_t aNumberOfChannels)
|
||||
{
|
||||
if (aNumberOfChannels == 0) {
|
||||
return false;
|
||||
}
|
||||
if (mBuffer.Length() == 0) {
|
||||
if (!mBuffer.SetLength(aNumberOfChannels)) {
|
||||
return false;
|
||||
}
|
||||
const int32_t numFrames = NS_lround(mMaxDelay) * IdealAudioRate();
|
||||
for (uint32_t channel = 0; channel < aNumberOfChannels; ++channel) {
|
||||
if (!mBuffer[channel].SetLength(numFrames)) {
|
||||
return false;
|
||||
}
|
||||
memset(mBuffer[channel].Elements(), 0, numFrames * sizeof(float));
|
||||
}
|
||||
} else if (mBuffer.Length() != aNumberOfChannels) {
|
||||
// TODO: Handle changes in the channel count
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
|
||||
const AudioChunk& aInput,
|
||||
AudioChunk* aOutput,
|
||||
bool* aFinished)
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
const bool firstTime = !!!mBuffer.Length();
|
||||
const uint32_t numChannels = aInput.mChannelData.Length();
|
||||
|
||||
if (!EnsureBuffer(numChannels)) {
|
||||
aOutput->SetNull(0);
|
||||
return;
|
||||
}
|
||||
|
||||
AllocateAudioBlock(numChannels, aOutput);
|
||||
|
||||
double delayTime = 0;
|
||||
float computedDelay[WEBAUDIO_BLOCK_SIZE];
|
||||
// Use a smoothing range of 20ms
|
||||
const double smoothingRate = WebAudioUtils::ComputeSmoothingRate(0.02, IdealAudioRate());
|
||||
|
||||
if (mDelay.HasSimpleValue()) {
|
||||
delayTime = std::max(0.0, std::min(mMaxDelay, double(mDelay.GetValue())));
|
||||
if (firstTime) {
|
||||
// Initialize this only the first time to make sure that mCurrentDelayTime
|
||||
// has a valid value when we try to change the delay time further below.
|
||||
mCurrentDelayTime = delayTime;
|
||||
}
|
||||
} else {
|
||||
// Compute the delay values for the duration of the input AudioChunk
|
||||
TrackTicks tick = aStream->GetCurrentPosition();
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
computedDelay[counter] = std::max(0.0, std::min(mMaxDelay,
|
||||
double(mDelay.GetValueAtTime<TrackTicks>(tick + counter))));
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t channel = 0; channel < numChannels; ++channel) {
|
||||
double currentDelayTime = mCurrentDelayTime;
|
||||
uint32_t writeIndex = mWriteIndex;
|
||||
|
||||
float* buffer = mBuffer[channel].Elements();
|
||||
const uint32_t bufferLength = mBuffer[channel].Length();
|
||||
const float* input = static_cast<const float*>(aInput.mChannelData[channel]);
|
||||
float* output = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[channel]));
|
||||
|
||||
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
||||
if (mDelay.HasSimpleValue()) {
|
||||
// If the simple value has changed, smoothly approach it
|
||||
currentDelayTime += (delayTime - currentDelayTime) * smoothingRate;
|
||||
} else {
|
||||
currentDelayTime = computedDelay[i];
|
||||
}
|
||||
|
||||
// Write the input sample to the correct location in our buffer
|
||||
buffer[writeIndex] = input[i];
|
||||
|
||||
// Now, determine the correct read position. We adjust the read position to be
|
||||
// from currentDelayTime seconds in the past. We also interpolate the two input
|
||||
// frames in case the read position does not match an integer index.
|
||||
double readPosition = writeIndex + bufferLength -
|
||||
(currentDelayTime * IdealAudioRate());
|
||||
if (readPosition >= bufferLength) {
|
||||
readPosition -= bufferLength;
|
||||
}
|
||||
MOZ_ASSERT(readPosition >= 0.0, "Why are we reading before the beginning of the buffer?");
|
||||
|
||||
// Here is a the reason why readIndex1 and readIndex will never be out
|
||||
// of bounds. The maximum value for bufferLength is 180 * 48000 (see
|
||||
// AudioContext::CreateDelay). The maximum value for mCurrentDelay is
|
||||
// 180.0, so initially readPosition cannot be more than bufferLength +
|
||||
// a fraction less than 1. Then we take care of that case by
|
||||
// subtracting bufferLength from it if needed. So, if
|
||||
// |bufferLength-readPosition<1.0|, readIndex1 will end up being zero.
|
||||
// If |1.0<=bufferLength-readPosition<2.0|, readIndex1 will be
|
||||
// bufferLength-1 and readIndex2 will be 0.
|
||||
int readIndex1 = int(readPosition);
|
||||
int readIndex2 = (readIndex1 + 1) % bufferLength;
|
||||
double interpolationFactor = readPosition - readIndex1;
|
||||
|
||||
output[i] = (1.0 - interpolationFactor) * buffer[readIndex1] +
|
||||
interpolationFactor * buffer[readIndex2];
|
||||
writeIndex = (writeIndex + 1) % bufferLength;
|
||||
}
|
||||
|
||||
// Remember currentDelayTime and writeIndex for the next ProduceAudioBlock
|
||||
// call when processing the last channel.
|
||||
if (channel == numChannels - 1) {
|
||||
mCurrentDelayTime = currentDelayTime;
|
||||
mWriteIndex = writeIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mDelay;
|
||||
// Maximum delay time in seconds
|
||||
double mMaxDelay;
|
||||
// Circular buffer for capturing delayed samples.
|
||||
AutoFallibleTArray<FallibleTArray<float>, 2> mBuffer;
|
||||
// Write index for the buffer, to write the frames to the correct index of the buffer
|
||||
// given the current delay.
|
||||
uint32_t mWriteIndex;
|
||||
// Current delay time, in seconds
|
||||
double mCurrentDelayTime;
|
||||
};
|
||||
|
||||
DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
|
||||
: AudioNode(aContext)
|
||||
, mDelay(new AudioParam(this, Callback, 0.0f, 0.0f, float(aMaxDelay)))
|
||||
, mDelay(new AudioParam(this, SendDelayToStream, 0.0f, 0.0f, float(aMaxDelay)))
|
||||
{
|
||||
DelayNodeEngine* engine = new DelayNodeEngine(aContext->Destination());
|
||||
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
|
||||
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
|
||||
AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
|
||||
ns->SetDoubleParameter(DelayNodeEngine::MAX_DELAY, aMaxDelay);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -31,6 +216,13 @@ DelayNode::WrapObject(JSContext* aCx, JSObject* aScope)
|
|||
return DelayNodeBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
DelayNode::SendDelayToStream(AudioNode* aNode)
|
||||
{
|
||||
DelayNode* This = static_cast<DelayNode*>(aNode);
|
||||
SendTimelineParameterToStream(This, DelayNodeEngine::DELAY, *This->mDelay);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,14 @@ public:
|
|||
return mDelay;
|
||||
}
|
||||
|
||||
virtual bool SupportsMediaStreams() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static void SendDelayToStream(AudioNode* aNode);
|
||||
|
||||
private:
|
||||
nsRefPtr<AudioParam> mDelay;
|
||||
};
|
||||
|
|
|
@ -21,11 +21,11 @@ struct ConvertTimeToTickHelper
|
|||
TrackRate sampleRate = IdealAudioRate();
|
||||
|
||||
ConvertTimeToTickHelper* This = static_cast<ConvertTimeToTickHelper*> (aClosure);
|
||||
TrackTicks tick = This->mSourceStream->GetCurrentPosition();
|
||||
StreamTime streamTime = TicksToTimeRoundDown(sampleRate, tick);
|
||||
GraphTime graphTime = This->mSourceStream->StreamTimeToGraphTime(streamTime);
|
||||
StreamTime destinationStreamTime = This->mDestinationStream->GraphTimeToStreamTime(graphTime);
|
||||
return TimeToTicksRoundDown(sampleRate, destinationStreamTime + SecondsToMediaTime(aTime));
|
||||
TrackTicks tick = This->mDestinationStream->GetCurrentPosition();
|
||||
StreamTime destinationStreamTime = TicksToTimeRoundDown(sampleRate, tick);
|
||||
GraphTime graphTime = This->mDestinationStream->StreamTimeToGraphTime(destinationStreamTime);
|
||||
StreamTime streamTime = This->mSourceStream->GraphTimeToStreamTime(graphTime);
|
||||
return TimeToTicksRoundDown(sampleRate, streamTime + SecondsToMediaTime(aTime));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,15 @@ struct WebAudioUtils {
|
|||
return fabs(v1 - v2) < 1e-7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes an exponential smoothing rate for a time based variable
|
||||
* over aDuration seconds.
|
||||
*/
|
||||
static double ComputeSmoothingRate(double aDuration, double aSampleRate)
|
||||
{
|
||||
return 1.0 - std::exp(-1.0 / (aDuration * aSampleRate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts AudioParamTimeline floating point time values to tick values
|
||||
* with respect to a source and a destination AudioNodeStream.
|
||||
|
|
|
@ -215,7 +215,7 @@ void TestEventRemoval()
|
|||
is(timeline.GetEventCount(), 1u, "Should successfully delete two events");
|
||||
}
|
||||
|
||||
void TestBeforeFirstEvent()
|
||||
void TestBeforeFirstEventSetValue()
|
||||
{
|
||||
Timeline timeline(10.0f);
|
||||
|
||||
|
@ -225,6 +225,36 @@ void TestBeforeFirstEvent()
|
|||
is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event");
|
||||
}
|
||||
|
||||
void TestBeforeFirstEventSetTarget()
|
||||
{
|
||||
Timeline timeline(10.0f);
|
||||
|
||||
ErrorResultMock rv;
|
||||
|
||||
timeline.SetTargetAtTime(20.0f, 1.0, 5.0, rv);
|
||||
is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event");
|
||||
}
|
||||
|
||||
void TestBeforeFirstEventLinearRamp()
|
||||
{
|
||||
Timeline timeline(10.0f);
|
||||
|
||||
ErrorResultMock rv;
|
||||
|
||||
timeline.LinearRampToValueAtTime(20.0f, 1.0, rv);
|
||||
is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event");
|
||||
}
|
||||
|
||||
void TestBeforeFirstEventExponentialRamp()
|
||||
{
|
||||
Timeline timeline(10.0f);
|
||||
|
||||
ErrorResultMock rv;
|
||||
|
||||
timeline.ExponentialRampToValueAtTime(20.0f, 1.0, rv);
|
||||
is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event");
|
||||
}
|
||||
|
||||
void TestAfterLastValueEvent()
|
||||
{
|
||||
Timeline timeline(10.0f);
|
||||
|
@ -361,7 +391,10 @@ int main()
|
|||
TestInvalidEvents();
|
||||
TestEventReplacement();
|
||||
TestEventRemoval();
|
||||
TestBeforeFirstEvent();
|
||||
TestBeforeFirstEventSetValue();
|
||||
TestBeforeFirstEventSetTarget();
|
||||
TestBeforeFirstEventLinearRamp();
|
||||
TestBeforeFirstEventExponentialRamp();
|
||||
TestAfterLastValueEvent();
|
||||
TestAfterLastTargetValueEvent();
|
||||
TestAfterLastTargetValueEventWithValueSet();
|
||||
|
|
|
@ -32,6 +32,9 @@ GetUserMediaLog()
|
|||
|
||||
#include "MediaEngineWebRTC.h"
|
||||
#include "ImageContainer.h"
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -43,6 +46,20 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
|||
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
|
||||
|
||||
// get the JVM
|
||||
JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
|
||||
|
||||
JNIEnv *env;
|
||||
jint res = jvm->AttachCurrentThread(&env, NULL);
|
||||
|
||||
webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context);
|
||||
|
||||
env->DeleteGlobalRef(context);
|
||||
#endif
|
||||
|
||||
if (!mVideoEngine) {
|
||||
if (!(mVideoEngine = webrtc::VideoEngine::Create())) {
|
||||
return;
|
||||
|
|
|
@ -55,7 +55,12 @@ function EventManager(sr) {
|
|||
for (var i = 0; i < allEvents.length; i++) {
|
||||
(function (eventName) {
|
||||
sr["on" + eventName] = function (evt) {
|
||||
ok(false, "unexpected event: " + eventName);
|
||||
var message = "unexpected event: " + eventName;
|
||||
if (eventName == "error") {
|
||||
message += " -- " + evt.message;
|
||||
}
|
||||
|
||||
ok(false, message);
|
||||
if (self.done) self.done();
|
||||
};
|
||||
})(allEvents[i]);
|
||||
|
|
|
@ -925,8 +925,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
|
|||
// Only style bindings get their prototypes unhooked. First do ourselves.
|
||||
if (mIsStyleBinding) {
|
||||
// Now the binding dies. Unhook our prototypes.
|
||||
if (mPrototypeBinding->HasImplementation()) {
|
||||
nsIScriptGlobalObject *global = aOldDocument->GetScopeObject();
|
||||
if (mPrototypeBinding->HasImplementation()) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(
|
||||
aOldDocument->GetScopeObject());
|
||||
if (global) {
|
||||
JSObject *scope = global->GetGlobalJSObject();
|
||||
// scope might be null if we've cycle-collected the global
|
||||
|
|
|
@ -41,14 +41,16 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CI
|
|||
|
||||
// An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile
|
||||
// properties and methods of XBL bindings against.
|
||||
class nsXBLDocGlobalObject : public nsIScriptGlobalObject,
|
||||
public nsIScriptObjectPrincipal
|
||||
class nsXBLDocGlobalObject : public nsIScriptGlobalObject
|
||||
{
|
||||
public:
|
||||
nsXBLDocGlobalObject(nsXBLDocumentInfo *aGlobalObjectOwner);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
// nsIGlobalObject methods
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
|
||||
// nsIScriptGlobalObject methods
|
||||
virtual nsresult EnsureScriptEnvironment();
|
||||
|
@ -58,7 +60,6 @@ public:
|
|||
}
|
||||
|
||||
virtual nsIScriptContext *GetContext();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
virtual void OnFinalize(JSObject* aObject);
|
||||
virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
|
||||
|
||||
|
@ -199,6 +200,7 @@ NS_IMPL_CYCLE_COLLECTION_1(nsXBLDocGlobalObject, mScriptContext)
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding,
|
|||
// nsXBLProtoImplAnonymousMethod::Execute
|
||||
nsIDocument* document = aBinding->GetBoundElement()->OwnerDoc();
|
||||
|
||||
nsIScriptGlobalObject *global = document->GetScopeObject();
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(document->GetScopeObject());
|
||||
if (!global) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context = global->GetContext();
|
||||
|
@ -164,7 +164,7 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
|
|||
}
|
||||
|
||||
nsIDocument *ownerDoc = aBoundElement->OwnerDoc();
|
||||
nsIScriptGlobalObject *sgo;
|
||||
nsIGlobalObject *sgo;
|
||||
|
||||
if (!(sgo = ownerDoc->GetScopeObject())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
|
|
@ -262,7 +262,7 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
|
|||
boundDocument = content->OwnerDoc();
|
||||
}
|
||||
|
||||
boundGlobal = boundDocument->GetScopeObject();
|
||||
boundGlobal = do_QueryInterface(boundDocument->GetScopeObject());
|
||||
}
|
||||
|
||||
if (!boundGlobal)
|
||||
|
|
|
@ -71,7 +71,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
|||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aLoadedAsData,
|
||||
nsIScriptGlobalObject* aEventObject,
|
||||
nsIGlobalObject* aEventObject,
|
||||
DocumentFlavor aFlavor)
|
||||
{
|
||||
// Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
|
||||
|
@ -127,8 +127,12 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
|||
return rv;
|
||||
}
|
||||
|
||||
d->SetScriptHandlingObject(aEventObject);
|
||||
|
||||
if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
|
||||
d->SetScriptHandlingObject(sgo);
|
||||
} else if (aEventObject){
|
||||
d->SetScopeObject(aEventObject);
|
||||
}
|
||||
|
||||
if (isHTML) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
|
||||
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
|
||||
|
|
|
@ -40,8 +40,7 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
|||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
|
||||
class nsXULPDGlobalObject : public nsIScriptGlobalObject,
|
||||
public nsIScriptObjectPrincipal
|
||||
class nsXULPDGlobalObject : public nsIScriptGlobalObject
|
||||
{
|
||||
public:
|
||||
nsXULPDGlobalObject(nsXULPrototypeDocument* owner);
|
||||
|
@ -49,11 +48,13 @@ public:
|
|||
// nsISupports interface
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
// nsIGlobalJSObjectHolder methods
|
||||
virtual JSObject* GetGlobalJSObject();
|
||||
|
||||
// nsIScriptGlobalObject methods
|
||||
virtual void OnFinalize(JSObject* aObject);
|
||||
virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
|
||||
|
||||
virtual JSObject* GetGlobalJSObject();
|
||||
virtual nsresult EnsureScriptEnvironment();
|
||||
|
||||
virtual nsIScriptContext *GetScriptContext();
|
||||
|
@ -729,6 +730,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPDGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \
|
||||
-I$(srcdir)/../../content/src \
|
||||
-I$(srcdir)/../../../../dom/base \
|
||||
-I$(srcdir)/../../../../layout/xul/tree/ \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nsArrayUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsXMLHttpRequest.h"
|
||||
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
|
@ -174,9 +175,10 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
|
|||
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(scriptObject);
|
||||
req->Init(docPrincipal, context, owner ? owner->GetOuterWindow() : nullptr,
|
||||
nullptr);
|
||||
rv = req->Init(docPrincipal, context,
|
||||
scriptObject ? scriptObject : doc->GetScopeObject(),
|
||||
nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, true,
|
||||
EmptyString(), EmptyString());
|
||||
|
|
|
@ -40,6 +40,7 @@ EXPORTS = \
|
|||
nsDOMString.h \
|
||||
nsIDOMClassInfo.h \
|
||||
nsIDOMScriptObjectFactory.h \
|
||||
nsIGlobalObject.h \
|
||||
nsIJSEventListener.h \
|
||||
nsIJSNativeInitializer.h \
|
||||
nsIScriptContext.h \
|
||||
|
|
|
@ -1506,6 +1506,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
|
|||
"nsIDOMWindowInternalWarning");
|
||||
}
|
||||
} else
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
|
||||
|
|
|
@ -260,7 +260,6 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
|
|||
public nsPIDOMWindow,
|
||||
public nsIScriptGlobalObject,
|
||||
public nsIDOMJSWindow,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIDOMStorageIndexedDB,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIInterfaceRequestor,
|
||||
|
@ -297,9 +296,11 @@ public:
|
|||
return EnsureInnerWindow() ? GetWrapper() : nullptr;
|
||||
}
|
||||
|
||||
// nsIGlobalJSObjectHolder
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
|
||||
// nsIScriptGlobalObject
|
||||
virtual nsIScriptContext *GetContext();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
JSObject *FastGetGlobalJSObject()
|
||||
{
|
||||
return mJSObject;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsIGlobalObject_h__
|
||||
#define nsIGlobalObject_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
|
||||
class JSObject;
|
||||
|
||||
#define NS_IGLOBALOBJECT_IID \
|
||||
{ 0x8503e9a9, 0x530, 0x4b26, \
|
||||
{ 0xae, 0x24, 0x18, 0xca, 0x38, 0xe5, 0xed, 0x17 } }
|
||||
|
||||
class nsIGlobalObject : public nsIScriptObjectPrincipal
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
|
||||
|
||||
virtual JSObject* GetGlobalJSObject() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject,
|
||||
NS_IGLOBALOBJECT_IID)
|
||||
|
||||
#endif // nsIGlobalObject_h__
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsScriptErrorEvent;
|
||||
|
@ -27,15 +28,17 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
|
|||
|
||||
|
||||
#define NS_ISCRIPTGLOBALOBJECT_IID \
|
||||
{ 0x92569431, 0x6e6e, 0x408a, \
|
||||
{ 0xa8, 0x8c, 0x45, 0x28, 0x5c, 0x1c, 0x85, 0x73 } }
|
||||
{ 0xde24b30a, 0x12c6, 0x4e5f, \
|
||||
{ 0xa8, 0x5e, 0x90, 0xcd, 0xfb, 0x6c, 0x54, 0x51 } }
|
||||
|
||||
/**
|
||||
* The global object which keeps a script context for each supported script
|
||||
* language. This often used to store per-window global state.
|
||||
* This is a heavyweight interface implemented only by DOM globals, and
|
||||
* it might go away some time in the future.
|
||||
*/
|
||||
|
||||
class nsIScriptGlobalObject : public nsISupports
|
||||
class nsIScriptGlobalObject : public nsIGlobalObject
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTGLOBALOBJECT_IID)
|
||||
|
@ -54,8 +57,6 @@ public:
|
|||
* Get a script context (WITHOUT added reference) for the specified language.
|
||||
*/
|
||||
virtual nsIScriptContext *GetScriptContext() = 0;
|
||||
|
||||
virtual JSObject* GetGlobalJSObject() = 0;
|
||||
|
||||
nsIScriptContext* GetContext() {
|
||||
return GetScriptContext();
|
||||
|
|
|
@ -19,7 +19,9 @@ def generate_binding_header(config, outputprefix, srcprefix, webidlfile):
|
|||
with open(filename, 'wb') as f:
|
||||
f.write(root.declare())
|
||||
with open(depsname, 'wb') as f:
|
||||
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for x in root.deps()))
|
||||
# Sort so that our output is stable
|
||||
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for
|
||||
x in sorted(root.deps())))
|
||||
|
||||
def generate_binding_cpp(config, outputprefix, srcprefix, webidlfile):
|
||||
"""
|
||||
|
@ -33,7 +35,8 @@ def generate_binding_cpp(config, outputprefix, srcprefix, webidlfile):
|
|||
with open(filename, 'wb') as f:
|
||||
f.write(root.define())
|
||||
with open(depsname, 'wb') as f:
|
||||
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for x in root.deps()))
|
||||
f.write("\n".join(filename + ": " + os.path.join(srcprefix, x) for
|
||||
x in sorted(root.deps())))
|
||||
|
||||
def main():
|
||||
|
||||
|
|
|
@ -640,6 +640,23 @@ XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
VariantToJsval(JSContext* aCx, JSObject* aScope, nsIVariant* aVariant,
|
||||
JS::Value* aRetval)
|
||||
{
|
||||
nsresult rv;
|
||||
XPCLazyCallContext lccx(JS_CALLER, aCx, aScope);
|
||||
if (!XPCVariant::VariantDataToJS(lccx, aVariant, &rv, aRetval)) {
|
||||
// Does it throw? Who knows
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
Throw<true>(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
|
|
|
@ -834,6 +834,11 @@ bool
|
|||
XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
|
||||
const nsIID* iid, bool allowNativeWrapper, JS::Value* rval);
|
||||
|
||||
// Special-cased wrapping for variants
|
||||
bool
|
||||
VariantToJsval(JSContext* aCx, JSObject* aScope, nsIVariant* aVariant,
|
||||
JS::Value* aRetval);
|
||||
|
||||
// Wrap an object "p" which is not using WebIDL bindings yet. This _will_
|
||||
// actually work on WebIDL binding objects that are wrappercached, but will be
|
||||
// much slower than WrapNewBindingObject. "cache" must either be null or be the
|
||||
|
@ -849,6 +854,18 @@ WrapObject(JSContext* cx, JSObject* scope, T* p, nsWrapperCache* cache,
|
|||
return XPCOMObjectToJsval(cx, scope, helper, iid, true, vp);
|
||||
}
|
||||
|
||||
// A specialization of the above for nsIVariant, because that needs to
|
||||
// do something different.
|
||||
template<>
|
||||
inline bool
|
||||
WrapObject<nsIVariant>(JSContext* cx, JSObject* scope, nsIVariant* p,
|
||||
nsWrapperCache* cache, const nsIID* iid, JS::Value* vp)
|
||||
{
|
||||
MOZ_ASSERT(iid);
|
||||
MOZ_ASSERT(iid->Equals(NS_GET_IID(nsIVariant)));
|
||||
return VariantToJsval(cx, scope, p, vp);
|
||||
}
|
||||
|
||||
// Wrap an object "p" which is not using WebIDL bindings yet. Just like the
|
||||
// variant that takes an nsWrapperCache above, but will try to auto-derive the
|
||||
// nsWrapperCache* from "p".
|
||||
|
|
|
@ -322,6 +322,7 @@ DOMInterfaces = {
|
|||
{
|
||||
'hasXPConnectImpls': True,
|
||||
'concrete': False,
|
||||
'jsImplParent': 'nsDOMEventTargetHelper'
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
|
@ -1178,6 +1179,16 @@ DOMInterfaces = {
|
|||
'register': False,
|
||||
},
|
||||
|
||||
'TestCImplementedInterface' : {
|
||||
'headerFile': 'TestCImplementedInterface.h',
|
||||
'register': False,
|
||||
},
|
||||
|
||||
'TestCImplementedInterface2' : {
|
||||
'headerFile': 'TestCImplementedInterface.h',
|
||||
'register': False,
|
||||
},
|
||||
|
||||
'TestJSImplInterface' : {
|
||||
# Keep this in sync with TestExampleInterface
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
|
@ -1196,6 +1207,37 @@ DOMInterfaces = {
|
|||
'attributeRenamedFrom': 'attributeRenamedTo' }
|
||||
},
|
||||
|
||||
'TestJSImplInterface' : {
|
||||
# Keep this in sync with TestExampleInterface
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestJSImplInterface2' : {
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestJSImplInterface3' : {
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestJSImplInterface4' : {
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestJSImplInterface5' : {
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestJSImplInterface6' : {
|
||||
'headerFile': 'TestJSImplGenBinding.h',
|
||||
'register': False
|
||||
},
|
||||
|
||||
'TestExternalInterface' : {
|
||||
'nativeType': 'mozilla::dom::TestExternalInterface',
|
||||
'headerFile': 'TestBindingHeader.h',
|
||||
|
|
|
@ -37,6 +37,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CallbackInterface without any sort of interesting games with
|
||||
* compartments, for cases when you want to just use the existing object
|
||||
* as-is. This constructor can never fail.
|
||||
*/
|
||||
explicit CallbackInterface(JSObject* aCallback)
|
||||
: CallbackObject(aCallback)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetCallableProperty(JSContext* cx, const char* aPropName,
|
||||
JS::Value* aCallable);
|
||||
|
|
|
@ -62,15 +62,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Set mCallback before we hold, on the off chance that a GC could somehow
|
||||
// happen in there... (which would be pretty odd, granted).
|
||||
mCallback = aCallback;
|
||||
// Make sure we'll be able to drop as needed
|
||||
nsLayoutStatics::AddRef();
|
||||
NS_HOLD_JS_OBJECTS(this, CallbackObject);
|
||||
Init(aCallback);
|
||||
*aInited = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CallbackObject without any sort of interesting games with
|
||||
* compartments, for cases when you want to just use the existing object
|
||||
* as-is. This constructor can never fail.
|
||||
*/
|
||||
explicit CallbackObject(JSObject* aCallback)
|
||||
{
|
||||
Init(aCallback);
|
||||
}
|
||||
|
||||
virtual ~CallbackObject()
|
||||
{
|
||||
DropCallback();
|
||||
|
@ -101,16 +106,23 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
explicit CallbackObject(CallbackObject* aCallbackFunction)
|
||||
: mCallback(aCallbackFunction->mCallback)
|
||||
explicit CallbackObject(CallbackObject* aCallbackObject)
|
||||
{
|
||||
Init(aCallbackObject->mCallback);
|
||||
}
|
||||
|
||||
private:
|
||||
inline void Init(JSObject* aCallback)
|
||||
{
|
||||
// Set mCallback before we hold, on the off chance that a GC could somehow
|
||||
// happen in there... (which would be pretty odd, granted).
|
||||
mCallback = aCallback;
|
||||
// Make sure we'll be able to drop as needed
|
||||
nsLayoutStatics::AddRef();
|
||||
NS_HOLD_JS_OBJECTS(this, CallbackObject);
|
||||
}
|
||||
|
||||
protected:
|
||||
void DropCallback()
|
||||
{
|
||||
if (mCallback) {
|
||||
|
|
|
@ -478,7 +478,7 @@ class CGHeaders(CGWrapper):
|
|||
def __init__(self, descriptors, dictionaries, callbacks,
|
||||
callbackDescriptors,
|
||||
declareIncludes, defineIncludes, child,
|
||||
config=None, anyJSImplemented=False):
|
||||
config=None, jsImplementedDescriptors=[]):
|
||||
"""
|
||||
Builds a set of includes to cover |descriptors|.
|
||||
|
||||
|
@ -594,12 +594,20 @@ class CGHeaders(CGWrapper):
|
|||
# And we need BindingUtils.h so we can wrap "this" objects
|
||||
declareIncludes.add("mozilla/dom/BindingUtils.h")
|
||||
|
||||
if len(callbackDescriptors) != 0 or anyJSImplemented:
|
||||
if len(callbackDescriptors) != 0 or len(jsImplementedDescriptors) != 0:
|
||||
# We need CallbackInterface to serve as our parent class
|
||||
declareIncludes.add("mozilla/dom/CallbackInterface.h")
|
||||
# And we need BindingUtils.h so we can wrap "this" objects
|
||||
declareIncludes.add("mozilla/dom/BindingUtils.h")
|
||||
|
||||
# Also need to include the headers for ancestors of
|
||||
# JS-implemented interfaces.
|
||||
for jsImplemented in jsImplementedDescriptors:
|
||||
jsParent = jsImplemented.interface.parent
|
||||
if jsParent:
|
||||
parentDesc = jsImplemented.getDescriptor(jsParent.identifier.name)
|
||||
declareIncludes.add(parentDesc.jsImplParentHeader)
|
||||
|
||||
# Let the machinery do its thing.
|
||||
def _includeString(includes):
|
||||
return ''.join(['#include "%s"\n' % i for i in includes]) + '\n'
|
||||
|
@ -1105,13 +1113,16 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
|
|||
const DOMClass* domClass = GetDOMClass(js::UnwrapObject(instance));
|
||||
*bp = false;
|
||||
"""
|
||||
for iface in self.descriptor.interface.interfacesImplementingSelf:
|
||||
# Sort interaces implementing self by name so we get stable output.
|
||||
for iface in sorted(self.descriptor.interface.interfacesImplementingSelf,
|
||||
key=lambda iface: iface.identifier.name):
|
||||
hasInstanceCode += """
|
||||
if (domClass->mInterfaceChain[PrototypeTraits<prototypes::id::%s>::Depth] == prototypes::id::%s) {
|
||||
*bp = true;
|
||||
return true;
|
||||
}""" % (iface.identifier.name, iface.identifier.name)
|
||||
hasInstanceCode += "return true;"
|
||||
}
|
||||
""" % (iface.identifier.name, iface.identifier.name)
|
||||
hasInstanceCode += " return true;"
|
||||
return header + hasInstanceCode;
|
||||
|
||||
def isChromeOnly(m):
|
||||
|
@ -3910,8 +3921,9 @@ if (global.Failed()) {
|
|||
""" % globalObjectType))
|
||||
argsPre.append("global")
|
||||
|
||||
needsCx = needCx(returnType, arguments, self.extendedAttributes,
|
||||
descriptor)
|
||||
needsCx = (not descriptor.interface.isJSImplemented() and
|
||||
needCx(returnType, arguments, self.extendedAttributes,
|
||||
descriptor))
|
||||
if needsCx and not (static and descriptor.workers):
|
||||
argsPre.append("cx")
|
||||
|
||||
|
@ -5465,11 +5477,11 @@ class ClassConstructor(ClassItem):
|
|||
baseConstructors is a list of strings containing calls to base constructors,
|
||||
defaults to None.
|
||||
|
||||
body contains a string with the code for the constructor, defaults to None.
|
||||
body contains a string with the code for the constructor, defaults to empty.
|
||||
"""
|
||||
def __init__(self, args, inline=False, bodyInHeader=False,
|
||||
visibility="private", explicit=False, baseConstructors=None,
|
||||
body=None):
|
||||
body=""):
|
||||
self.args = args
|
||||
self.inline = inline or bodyInHeader
|
||||
self.bodyInHeader = bodyInHeader
|
||||
|
@ -5501,7 +5513,6 @@ class ClassConstructor(ClassItem):
|
|||
return ''
|
||||
|
||||
def getBody(self):
|
||||
assert self.body is not None
|
||||
return self.body
|
||||
|
||||
def declare(self, cgClass):
|
||||
|
@ -5543,7 +5554,7 @@ ${className}::${className}(${args})${initializationList}
|
|||
|
||||
class ClassDestructor(ClassItem):
|
||||
"""
|
||||
Used for adding a constructor to a CGClass.
|
||||
Used for adding a destructor to a CGClass.
|
||||
|
||||
inline should be True if the destructor should be marked inline.
|
||||
|
||||
|
@ -5553,17 +5564,22 @@ class ClassDestructor(ClassItem):
|
|||
visibility determines the visibility of the destructor (public,
|
||||
protected, private), defaults to private.
|
||||
|
||||
body contains a string with the code for the destructor, defaults to None.
|
||||
body contains a string with the code for the destructor, defaults to empty.
|
||||
|
||||
virtual determines whether the destructor is virtual, defaults to False.
|
||||
"""
|
||||
def __init__(self, inline=False, bodyInHeader=False,
|
||||
visibility="private", body=None):
|
||||
visibility="private", body='', virtual=False):
|
||||
self.inline = inline or bodyInHeader
|
||||
self.bodyInHeader = bodyInHeader
|
||||
self.body = body
|
||||
self.virtual = virtual
|
||||
ClassItem.__init__(self, None, visibility)
|
||||
|
||||
def getDecorators(self, declaring):
|
||||
decorators = []
|
||||
if self.virtual and declaring:
|
||||
decorators.append('virtual')
|
||||
if self.inline and declaring:
|
||||
decorators.append('inline')
|
||||
if decorators:
|
||||
|
@ -5571,7 +5587,6 @@ class ClassDestructor(ClassItem):
|
|||
return ''
|
||||
|
||||
def getBody(self):
|
||||
assert self.body is not None
|
||||
return self.body
|
||||
|
||||
def declare(self, cgClass):
|
||||
|
@ -6078,8 +6093,7 @@ const DOMClass Class = """ + DOMClass(self.descriptor) + """;
|
|||
class CGDOMJSProxyHandler_CGDOMJSProxyHandler(ClassConstructor):
|
||||
def __init__(self):
|
||||
ClassConstructor.__init__(self, [], inline=True, visibility="private",
|
||||
baseConstructors=["mozilla::dom::DOMProxyHandler(Class)"],
|
||||
body="")
|
||||
baseConstructors=["mozilla::dom::DOMProxyHandler(Class)"])
|
||||
|
||||
class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
|
||||
def __init__(self, descriptor):
|
||||
|
@ -7112,6 +7126,37 @@ class CGRegisterProtos(CGAbstractMethod):
|
|||
def definition_body(self):
|
||||
return self._defineMacro() + self._registerProtos() + self._undefineMacro()
|
||||
|
||||
def dependencySortObjects(objects, dependencyGetter, nameGetter):
|
||||
"""
|
||||
Sort IDL objects with dependencies on each other such that if A
|
||||
depends on B then B will come before A. This is needed for
|
||||
declaring C++ classes in the right order, for example. Objects
|
||||
that have no dependencies are just sorted by name.
|
||||
|
||||
objects should be something that can produce a set of objects
|
||||
(e.g. a set, iterator, list, etc).
|
||||
|
||||
dependencyGetter is something that, given an object, should return
|
||||
the set of objects it depends on.
|
||||
"""
|
||||
# XXXbz this will fail if we have two webidl files F1 and F2 such that F1
|
||||
# declares an object which depends on an object in F2, and F2 declares an
|
||||
# object (possibly a different one!) that depends on an object in F1. The
|
||||
# good news is that I expect this to never happen.
|
||||
sortedObjects = []
|
||||
objects = set(objects)
|
||||
while len(objects) != 0:
|
||||
# Find the dictionaries that don't depend on anything else
|
||||
# anymore and move them over.
|
||||
toMove = [o for o in objects if
|
||||
len(dependencyGetter(o) & objects) == 0]
|
||||
if len(toMove) == 0:
|
||||
raise TypeError("Loop in dependency graph\n" +
|
||||
"\n".join(o.location for o in objects))
|
||||
objects = objects - set(toMove)
|
||||
sortedObjects.extend(sorted(toMove, key=nameGetter))
|
||||
return sortedObjects
|
||||
|
||||
class CGBindingRoot(CGThing):
|
||||
"""
|
||||
Root codegen class for binding generation. Instantiate the class, and call
|
||||
|
@ -7156,7 +7201,7 @@ class CGBindingRoot(CGThing):
|
|||
for callback in workerCallbacks:
|
||||
workerIfaces.extend(getInterfacesFromCallback(callback))
|
||||
|
||||
for callbackDescriptor in callbackDescriptors:
|
||||
for callbackDescriptor in callbackDescriptors + jsImplemented:
|
||||
callbackDescriptorIfaces = [
|
||||
t.unroll().inner
|
||||
for t in getTypesFromDescriptor(callbackDescriptor)
|
||||
|
@ -7214,6 +7259,13 @@ class CGBindingRoot(CGThing):
|
|||
for t in getTypesFromDictionary(dictionary)
|
||||
if t.unroll().isCallback())
|
||||
|
||||
# Forward declarations for callback functions used in interfaces
|
||||
for desc in descriptors:
|
||||
forwardDeclares.extend(
|
||||
declareNativeType("mozilla::dom::" + str(t.unroll()))
|
||||
for t in getTypesFromDescriptor(desc)
|
||||
if t.unroll().isCallback())
|
||||
|
||||
forwardDeclares = CGList(forwardDeclares)
|
||||
|
||||
descriptorsWithPrototype = filter(lambda d: d.interface.hasInterfacePrototypeObject(),
|
||||
|
@ -7249,30 +7301,16 @@ class CGBindingRoot(CGThing):
|
|||
# here, because we have to generate these in order from least derived
|
||||
# to most derived so that class inheritance works out. We also have to
|
||||
# generate members before the dictionary that contains them.
|
||||
#
|
||||
# XXXbz this will fail if we have two webidl files A and B such that A
|
||||
# declares a dictionary which inherits from a dictionary in B and B
|
||||
# declares a dictionary (possibly a different one!) that inherits from a
|
||||
# dictionary in A. The good news is that I expect this to never happen.
|
||||
def sortDictionaries(dictionaries):
|
||||
reSortedDictionaries = []
|
||||
dictionaries = set(dictionaries)
|
||||
while len(dictionaries) != 0:
|
||||
# Find the dictionaries that don't depend on anything else
|
||||
# anymore and move them over.
|
||||
toMove = [d for d in dictionaries if
|
||||
len(CGDictionary.getDictionaryDependencies(d) &
|
||||
dictionaries) == 0]
|
||||
if len(toMove) == 0:
|
||||
raise TypeError("Loop in dictionary dependency graph")
|
||||
dictionaries = dictionaries - set(toMove)
|
||||
reSortedDictionaries.extend(toMove)
|
||||
return reSortedDictionaries
|
||||
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
|
||||
for d in sortDictionaries(workerDictionaries)])
|
||||
for d in
|
||||
dependencySortObjects(workerDictionaries,
|
||||
CGDictionary.getDictionaryDependencies,
|
||||
lambda d: d.identifier.name)])
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
|
||||
for d in sortDictionaries(mainDictionaries)])
|
||||
for d in
|
||||
dependencySortObjects(mainDictionaries,
|
||||
CGDictionary.getDictionaryDependencies,
|
||||
lambda d: d.identifier.name)])
|
||||
|
||||
# Do codegen for all the callbacks. Only do non-worker codegen for now,
|
||||
# since we don't have a sane setup yet for invoking callbacks in workers
|
||||
|
@ -7287,7 +7325,12 @@ class CGBindingRoot(CGThing):
|
|||
cgthings.extend([CGCallbackInterface(x) for x in callbackDescriptors])
|
||||
|
||||
# Do codegen for JS implemented classes
|
||||
for x in jsImplemented:
|
||||
def getParentDescriptor(desc):
|
||||
if not desc.interface.parent:
|
||||
return set()
|
||||
return { desc.getDescriptor(desc.interface.parent.identifier.name) }
|
||||
for x in dependencySortObjects(jsImplemented, getParentDescriptor,
|
||||
lambda d: d.interface.identifier.name):
|
||||
cgthings.append(CGCallbackInterface(x))
|
||||
cgthings.append(CGJSImplClass(x))
|
||||
|
||||
|
@ -7330,7 +7373,7 @@ class CGBindingRoot(CGThing):
|
|||
],
|
||||
curr,
|
||||
config,
|
||||
anyJSImplemented = len(jsImplemented) != 0)
|
||||
jsImplemented)
|
||||
|
||||
# Add include guards.
|
||||
curr = CGIncludeGuard(prefix, curr)
|
||||
|
@ -7985,7 +8028,8 @@ class CGJSImplMethod(CGNativeMember):
|
|||
signature,
|
||||
descriptor.getExtendedAttributes(method),
|
||||
breakAfter=breakAfter,
|
||||
variadicIsSequence=True)
|
||||
variadicIsSequence=True,
|
||||
passCxAsNeeded=False)
|
||||
self.signature = signature
|
||||
if isConstructor:
|
||||
self.body = self.getConstructorImpl()
|
||||
|
@ -8028,17 +8072,9 @@ class CGJSImplMethod(CGNativeMember):
|
|||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
// Construct the callback interface object.
|
||||
bool initOk;
|
||||
nsRefPtr<${callbackClass}> cbImpl = new ${callbackClass}(cx, nullptr, jsImplObj, &initOk);
|
||||
if (!initOk) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
// Build the actual implementation.
|
||||
nsRefPtr<${implClass}> impl = new ${implClass}(cbImpl, window);
|
||||
// Build the C++ implementation.
|
||||
nsRefPtr<${implClass}> impl = new ${implClass}(jsImplObj, window);
|
||||
return impl.forget();""").substitute({"implClass" : self.descriptor.name,
|
||||
"callbackClass" : jsImplName(self.descriptor.name),
|
||||
"contractId" : self.descriptor.interface.getJSImplementation()
|
||||
})
|
||||
|
||||
|
@ -8056,7 +8092,8 @@ class CGJSImplGetter(CGNativeMember):
|
|||
attr),
|
||||
(attr.type, []),
|
||||
descriptor.getExtendedAttributes(attr,
|
||||
getter=True))
|
||||
getter=True),
|
||||
passCxAsNeeded=False)
|
||||
self.body = self.getImpl()
|
||||
|
||||
def getImpl(self):
|
||||
|
@ -8071,7 +8108,8 @@ class CGJSImplSetter(CGNativeMember):
|
|||
(BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
[FakeArgument(attr.type, attr)]),
|
||||
descriptor.getExtendedAttributes(attr,
|
||||
setter=True))
|
||||
setter=True),
|
||||
passCxAsNeeded=False)
|
||||
self.body = self.getImpl()
|
||||
|
||||
def getImpl(self):
|
||||
|
@ -8083,36 +8121,84 @@ class CGJSImplClass(CGBindingImplClass):
|
|||
def __init__(self, descriptor):
|
||||
CGBindingImplClass.__init__(self, descriptor, CGJSImplMethod, CGJSImplGetter, CGJSImplSetter)
|
||||
|
||||
if descriptor.interface.parent:
|
||||
parentClass = descriptor.getDescriptor(
|
||||
descriptor.interface.parent.identifier.name).jsImplParent
|
||||
baseClasses = [ClassBase(parentClass)]
|
||||
isupportsDecl = "NS_DECL_ISUPPORTS_INHERITED"
|
||||
ccDecl = ("NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)" %
|
||||
(descriptor.name, parentClass))
|
||||
constructorBody = (
|
||||
"// Make sure we're an nsWrapperCache already\n"
|
||||
"MOZ_ASSERT(static_cast<nsWrapperCache*>(this));\n"
|
||||
"// And that our ancestor has called SetIsDOMBinding()\n"
|
||||
"MOZ_ASSERT(IsDOMBinding());")
|
||||
extradefinitions= string.Template(
|
||||
"NS_IMPL_CYCLE_COLLECTION_INHERITED_2(${ifaceName}, ${parentClass}, mImpl, mParent)\n"
|
||||
"NS_IMPL_ADDREF_INHERITED(${ifaceName}, ${parentClass})\n"
|
||||
"NS_IMPL_RELEASE_INHERITED(${ifaceName}, ${parentClass})\n"
|
||||
"NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(${ifaceName})\n"
|
||||
"NS_INTERFACE_MAP_END_INHERITING(${parentClass})\n").substitute(
|
||||
{ "ifaceName": self.descriptor.name,
|
||||
"parentClass": parentClass })
|
||||
else:
|
||||
baseClasses = [ClassBase("nsISupports"),
|
||||
ClassBase("nsWrapperCache")]
|
||||
isupportsDecl = "NS_DECL_CYCLE_COLLECTING_ISUPPORTS"
|
||||
ccDecl = ("NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(%s)" %
|
||||
descriptor.name)
|
||||
constructorBody = "SetIsDOMBinding();"
|
||||
extradefinitions= string.Template(
|
||||
"NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(${ifaceName}, mImpl, mParent)\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName})\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_RELEASE(${ifaceName})\n"
|
||||
"NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${ifaceName})\n"
|
||||
" NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY\n"
|
||||
" NS_INTERFACE_MAP_ENTRY(nsISupports)\n"
|
||||
"NS_INTERFACE_MAP_END\n").substitute({ "ifaceName": self.descriptor.name })
|
||||
|
||||
extradeclarations=(
|
||||
"public:\n"
|
||||
" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n"
|
||||
" NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(%s)\n"
|
||||
" %s\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"private:\n"
|
||||
" nsRefPtr<%s> mImpl;\n"
|
||||
" nsCOMPtr<nsISupports> mParent;\n"
|
||||
"\n" % (descriptor.name, jsImplName(descriptor.name)))
|
||||
"\n" % (isupportsDecl, ccDecl, jsImplName(descriptor.name)))
|
||||
|
||||
extradefinitions= string.Template(
|
||||
"NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(${ifaceName}, mImpl, mParent)\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName})\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_RELEASE(${ifaceName})\n"
|
||||
"NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${ifaceName})\n"
|
||||
" NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY\n"
|
||||
" NS_INTERFACE_MAP_ENTRY(nsISupports)\n"
|
||||
"NS_INTERFACE_MAP_END\n").substitute({ "ifaceName": self.descriptor.name })
|
||||
if descriptor.interface.hasChildInterfaces():
|
||||
decorators = ""
|
||||
# We need a public virtual destructor our subclasses can use
|
||||
destructor = ClassDestructor(virtual=True, visibility="public")
|
||||
else:
|
||||
decorators = "MOZ_FINAL"
|
||||
destructor = None
|
||||
|
||||
baseConstructors=["mImpl(new %s(aJSImplObject))" % jsImplName(descriptor.name),
|
||||
"mParent(aParent)"]
|
||||
parentInterface = descriptor.interface.parent
|
||||
while parentInterface:
|
||||
if parentInterface.isJSImplemented():
|
||||
baseConstructors = (
|
||||
[ "%s(aJSImplObject, aParent)" % parentClass ] +
|
||||
baseConstructors )
|
||||
break
|
||||
parentInterface = parentInterface.parent
|
||||
|
||||
constructor = ClassConstructor(
|
||||
[Argument("JSObject*", "aJSImplObject"),
|
||||
Argument("nsISupports*", "aParent")],
|
||||
visibility="public",
|
||||
baseConstructors=baseConstructors,
|
||||
body=constructorBody)
|
||||
|
||||
CGClass.__init__(self, descriptor.name,
|
||||
bases=[ClassBase("nsISupports"),
|
||||
ClassBase("nsWrapperCache")],
|
||||
constructors=[ClassConstructor([Argument(jsImplName(descriptor.name) + "*", "aImpl"),
|
||||
Argument("nsISupports*", "aParent")],
|
||||
visibility="public",
|
||||
baseConstructors=["mImpl(aImpl)",
|
||||
"mParent(aParent)"],
|
||||
body="SetIsDOMBinding();")],
|
||||
bases=baseClasses,
|
||||
constructors=[constructor],
|
||||
destructor=destructor,
|
||||
methods=self.methodDecls,
|
||||
decorators="MOZ_FINAL",
|
||||
decorators=decorators,
|
||||
extradeclarations=extradeclarations,
|
||||
extradefinitions=extradefinitions)
|
||||
|
||||
|
@ -8162,8 +8248,7 @@ class CGCallback(CGClass):
|
|||
visibility="public",
|
||||
baseConstructors=[
|
||||
"%s(cx, aOwner, aCallback, aInited)" % self.baseName
|
||||
],
|
||||
body="")]
|
||||
])]
|
||||
|
||||
def getMethodImpls(self, method):
|
||||
assert method.needThisHandling
|
||||
|
@ -8239,8 +8324,7 @@ class CGCallbackFunction(CGCallback):
|
|||
explicit=True,
|
||||
baseConstructors=[
|
||||
"CallbackFunction(aOther)"
|
||||
],
|
||||
body="")]
|
||||
])]
|
||||
|
||||
class CGCallbackInterface(CGCallback):
|
||||
def __init__(self, descriptor):
|
||||
|
@ -8256,6 +8340,16 @@ class CGCallbackInterface(CGCallback):
|
|||
CGCallback.__init__(self, iface, descriptor, "CallbackInterface",
|
||||
methods, getters=getters, setters=setters)
|
||||
|
||||
def getConstructors(self):
|
||||
return CGCallback.getConstructors(self) + [
|
||||
ClassConstructor(
|
||||
[Argument("JSObject*", "aCallback")],
|
||||
bodyInHeader=True,
|
||||
visibility="public",
|
||||
explicit=True,
|
||||
baseConstructors=["CallbackInterface(aCallback)"])
|
||||
]
|
||||
|
||||
class FakeMember():
|
||||
def __init__(self):
|
||||
self.treatUndefinedAs = self.treatNullAs = "Default"
|
||||
|
|
|
@ -211,6 +211,7 @@ class Descriptor(DescriptorProvider):
|
|||
nativeTypeDefault = "mozilla::dom::" + ifaceName
|
||||
|
||||
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
||||
self.jsImplParent = desc.get('jsImplParent', self.nativeType)
|
||||
|
||||
# Do something sane for JSObject
|
||||
if self.nativeType == "JSObject":
|
||||
|
@ -229,6 +230,10 @@ class Descriptor(DescriptorProvider):
|
|||
headerDefault = self.nativeType
|
||||
headerDefault = headerDefault.replace("::", "/") + ".h"
|
||||
self.headerFile = desc.get('headerFile', headerDefault)
|
||||
if self.jsImplParent == self.nativeType:
|
||||
self.jsImplParentHeader = self.headerFile
|
||||
else:
|
||||
self.jsImplParentHeader = self.jsImplParent.replace("::", "/") + ".h"
|
||||
|
||||
self.skipGen = desc.get('skipGen', False)
|
||||
|
||||
|
|
|
@ -506,6 +506,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||
# self.interfacesImplementingSelf is the set of interfaces that directly
|
||||
# have self as a consequential interface
|
||||
self.interfacesImplementingSelf = set()
|
||||
self._hasChildInterfaces = False
|
||||
|
||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||
|
||||
|
@ -567,6 +568,8 @@ class IDLInterface(IDLObjectWithScope):
|
|||
if self.parent:
|
||||
self.parent.finish(scope)
|
||||
|
||||
self.parent._hasChildInterfaces = True
|
||||
|
||||
# Callbacks must not inherit from non-callbacks or inherit from
|
||||
# anything that has consequential interfaces.
|
||||
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
|
||||
|
@ -977,6 +980,9 @@ class IDLInterface(IDLObjectWithScope):
|
|||
def isJSImplemented(self):
|
||||
return bool(self.getJSImplementation())
|
||||
|
||||
def hasChildInterfaces(self):
|
||||
return self._hasChildInterfaces
|
||||
|
||||
def _getDependentObjects(self):
|
||||
deps = set(self.members)
|
||||
deps.union(self.implementedInterfaces)
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef TestCImplementedInterface_h
|
||||
#define TestCImplementedInterface_h
|
||||
|
||||
#include "../TestJSImplGenBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class TestCImplementedInterface : public TestJSImplInterface
|
||||
{
|
||||
public:
|
||||
TestCImplementedInterface(JSObject* aJSImpl, nsISupports* aParent)
|
||||
: TestJSImplInterface(aJSImpl, aParent)
|
||||
{}
|
||||
};
|
||||
|
||||
class TestCImplementedInterface2 : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestCImplementedInterface2)
|
||||
|
||||
// We need a GetParentObject to make binding codegen happy
|
||||
nsISupports* GetParentObject();
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // TestCImplementedInterface_h
|
|
@ -311,22 +311,24 @@ interface TestJSImplInterface {
|
|||
//void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
|
||||
void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
|
||||
|
||||
/* The rest of these are untested.
|
||||
// Any types
|
||||
void passAny(any arg);
|
||||
void passOptionalAny(optional any arg);
|
||||
void passAnyDefaultNull(optional any arg = null);
|
||||
any receiveAny();
|
||||
|
||||
// object types
|
||||
void passObject(object arg);
|
||||
// object types. Unfortunately, non-nullable object is inconsistently
|
||||
// represented as either JSObject* (for callbacks) or JSObject& (for
|
||||
// non-callbacks), so we can't handle those yet. See bug 856911.
|
||||
//(BUG 856911) void passObject(object arg);
|
||||
void passNullableObject(object? arg);
|
||||
void passOptionalObject(optional object arg);
|
||||
//(BUG 856911) void passOptionalObject(optional object arg);
|
||||
void passOptionalNullableObject(optional object? arg);
|
||||
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
|
||||
object receiveObject();
|
||||
object? receiveNullableObject();
|
||||
|
||||
/* The rest of these are untested.
|
||||
// Union types
|
||||
void passUnion((object or long) arg);
|
||||
void passUnionWithNullable((object? or long) arg);
|
||||
|
@ -413,3 +415,9 @@ interface TestJSImplInterface {
|
|||
*/
|
||||
// If you add things here, add them to TestCodeGen as well
|
||||
};
|
||||
|
||||
interface TestCImplementedInterface : TestJSImplInterface {
|
||||
};
|
||||
|
||||
interface TestCImplementedInterface2 {
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- 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/.
|
||||
*/
|
||||
|
||||
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface2;1"]
|
||||
interface TestJSImplInterface2 : TestCImplementedInterface {
|
||||
};
|
||||
|
||||
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface3;1"]
|
||||
interface TestJSImplInterface3 : TestCImplementedInterface2 {
|
||||
};
|
||||
|
||||
// Important: TestJSImplInterface5 needs to come before TestJSImplInterface6 in
|
||||
// this file to test what it's trying to test.
|
||||
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface5;1"]
|
||||
interface TestJSImplInterface5 : TestJSImplInterface6 {
|
||||
};
|
||||
|
||||
// Important: TestJSImplInterface6 needs to come after TestJSImplInterface3 in
|
||||
// this file to test what it's trying to test.
|
||||
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface6;1"]
|
||||
interface TestJSImplInterface6 : TestJSImplInterface3 {
|
||||
};
|
||||
|
||||
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface4;1"]
|
||||
interface TestJSImplInterface4 : EventTarget {
|
||||
};
|
|
@ -30,67 +30,129 @@
|
|||
"DOMException exception: constant DATA_CLONE_ERR on exception interface prototype object": true,
|
||||
"DOMException exception: field code on exception interface prototype object": true,
|
||||
"DOMError interface: existence and properties of interface object": true,
|
||||
"DOMError interface constructor": true,
|
||||
"DOMError interface: existence and properties of interface prototype object": true,
|
||||
"DOMError interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"DOMError interface: attribute name": true,
|
||||
"Event interface: document.createEvent(\"Event\") must inherit property \"timeStamp\" with the proper type (14)": true,
|
||||
"Event interface: new Event(\"foo\") must inherit property \"timeStamp\" with the proper type (14)": true,
|
||||
"Event interface: document.createEvent(\"Event\") must have own property \"isTrusted\"": true,
|
||||
"Event interface: document.createEvent(\"Event\") must inherit property \"timeStamp\" with the proper type (15)": true,
|
||||
"Event interface: new Event(\"foo\") must have own property \"isTrusted\"": true,
|
||||
"Event interface: new Event(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true,
|
||||
"CustomEvent interface: existence and properties of interface object": true,
|
||||
"CustomEvent interface constructor": true,
|
||||
"CustomEvent interface: existence and properties of interface prototype object": true,
|
||||
"CustomEvent interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"CustomEvent interface: attribute detail": true,
|
||||
"Stringification of new CustomEvent(\"foo\")": "debug",
|
||||
"Event interface: new CustomEvent(\"foo\") must inherit property \"timeStamp\" with the proper type (14)": true,
|
||||
"CustomEvent interface: calling initCustomEvent(DOMString,boolean,boolean,any) on new CustomEvent(\"foo\") with too few arguments must throw TypeError": true,
|
||||
"Event interface: new CustomEvent(\"foo\") must have own property \"isTrusted\"": true,
|
||||
"Event interface: new CustomEvent(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true,
|
||||
"Event interface: calling initEvent(DOMString,boolean,boolean) on new CustomEvent(\"foo\") with too few arguments must throw TypeError": true,
|
||||
"EventListener interface: existence and properties of interface object": true,
|
||||
"EventListener interface: existence and properties of interface prototype object": true,
|
||||
"EventListener interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"EventListener interface: operation handleEvent(Event)": true,
|
||||
"MutationCallback interface: existence and properties of interface object": true,
|
||||
"MutationCallback interface: existence and properties of interface prototype object": true,
|
||||
"MutationCallback interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"MutationCallback interface: operation handleEvent(MutationRecord,MutationObserver)": true,
|
||||
"MutationObserver interface: operation observe(Node,MutationObserverInit)": true,
|
||||
"Document interface: attribute children": true,
|
||||
"Document interface: attribute firstElementChild": true,
|
||||
"Document interface: attribute lastElementChild": true,
|
||||
"Document interface: attribute childElementCount": true,
|
||||
"Document interface: operation prepend(union)": true,
|
||||
"Document interface: operation append(union)": true,
|
||||
"Document interface: xmlDoc must inherit property \"children\" with the proper type (24)": true,
|
||||
"Document interface: xmlDoc must inherit property \"firstElementChild\" with the proper type (25)": true,
|
||||
"Document interface: xmlDoc must inherit property \"lastElementChild\" with the proper type (26)": true,
|
||||
"Document interface: xmlDoc must inherit property \"childElementCount\" with the proper type (27)": true,
|
||||
"Document interface: xmlDoc must inherit property \"prepend\" with the proper type (28)": true,
|
||||
"Document interface: calling prepend(union) on xmlDoc with too few arguments must throw TypeError": true,
|
||||
"Document interface: xmlDoc must inherit property \"append\" with the proper type (29)": true,
|
||||
"Document interface: calling append(union) on xmlDoc with too few arguments must throw TypeError": true,
|
||||
"DocumentFragment interface: attribute children": true,
|
||||
"DocumentFragment interface: attribute firstElementChild": true,
|
||||
"DocumentFragment interface: attribute lastElementChild": true,
|
||||
"DocumentFragment interface: attribute childElementCount": true,
|
||||
"DocumentFragment interface: operation prepend(union)": true,
|
||||
"DocumentFragment interface: operation append(union)": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"children\" with the proper type (0)": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"firstElementChild\" with the proper type (1)": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"lastElementChild\" with the proper type (2)": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"childElementCount\" with the proper type (3)": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"prepend\" with the proper type (4)": true,
|
||||
"DocumentFragment interface: calling prepend(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
|
||||
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"append\" with the proper type (5)": true,
|
||||
"DocumentFragment interface: calling append(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
|
||||
"DocumentType interface: attribute previousElementSibling": true,
|
||||
"DocumentType interface: attribute nextElementSibling": true,
|
||||
"DocumentType interface: operation before(union)": true,
|
||||
"DocumentType interface: operation after(union)": true,
|
||||
"DocumentType interface: operation replace(union)": true,
|
||||
"DocumentType interface: operation remove()": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"remove\" with the proper type (3)": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"previousElementSibling\" with the proper type (3)": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"nextElementSibling\" with the proper type (4)": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"before\" with the proper type (5)": true,
|
||||
"DocumentType interface: calling before(union) on document.doctype with too few arguments must throw TypeError": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"after\" with the proper type (6)": true,
|
||||
"DocumentType interface: calling after(union) on document.doctype with too few arguments must throw TypeError": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"replace\" with the proper type (7)": true,
|
||||
"DocumentType interface: calling replace(union) on document.doctype with too few arguments must throw TypeError": true,
|
||||
"DocumentType interface: document.doctype must inherit property \"remove\" with the proper type (8)": true,
|
||||
"Element interface: attribute namespaceURI": true,
|
||||
"Element interface: attribute prefix": true,
|
||||
"Element interface: attribute localName": true,
|
||||
"Element interface: attribute className": true,
|
||||
"Element interface: operation prepend(union)": true,
|
||||
"Element interface: operation append(union)": true,
|
||||
"Element interface: operation before(union)": true,
|
||||
"Element interface: operation after(union)": true,
|
||||
"Element interface: operation replace(union)": true,
|
||||
"Element interface: operation remove()": true,
|
||||
"Element interface: element must inherit property \"className\" with the proper type (5)": true,
|
||||
"Element interface: element must inherit property \"remove\" with the proper type (25)": true,
|
||||
"Element interface: element must inherit property \"prepend\" with the proper type (23)": true,
|
||||
"Element interface: calling prepend(union) on element with too few arguments must throw TypeError": true,
|
||||
"Element interface: element must inherit property \"append\" with the proper type (24)": true,
|
||||
"Element interface: calling append(union) on element with too few arguments must throw TypeError": true,
|
||||
"Element interface: element must inherit property \"before\" with the proper type (27)": true,
|
||||
"Element interface: calling before(union) on element with too few arguments must throw TypeError": true,
|
||||
"Element interface: element must inherit property \"after\" with the proper type (28)": true,
|
||||
"Element interface: calling after(union) on element with too few arguments must throw TypeError": true,
|
||||
"Element interface: element must inherit property \"replace\" with the proper type (29)": true,
|
||||
"Element interface: calling replace(union) on element with too few arguments must throw TypeError": true,
|
||||
"Element interface: element must inherit property \"remove\" with the proper type (30)": true,
|
||||
"Attr interface: existence and properties of interface object": true,
|
||||
"Attr interface: existence and properties of interface prototype object": true,
|
||||
"Attr interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"Attr interface: attribute name": true,
|
||||
"Attr interface: attribute value": true,
|
||||
"Attr interface: attribute name": true,
|
||||
"Stringification of document.querySelector(\"[id]\").attributes[0]": "debug",
|
||||
"CharacterData interface: attribute previousElementSibling": true,
|
||||
"CharacterData interface: attribute nextElementSibling": true,
|
||||
"CharacterData interface: operation before(union)": true,
|
||||
"CharacterData interface: operation after(union)": true,
|
||||
"CharacterData interface: operation replace(union)": true,
|
||||
"CharacterData interface: operation remove()": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"remove\" with the proper type (7)": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"remove\" with the proper type (7)": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"remove\" with the proper type (7)": true,
|
||||
"NodeFilter interface: existence and properties of interface prototype object": true,
|
||||
"NodeFilter interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"NodeFilter interface: constant FILTER_ACCEPT on interface prototype object": true,
|
||||
"NodeFilter interface: constant FILTER_REJECT on interface prototype object": true,
|
||||
"NodeFilter interface: constant FILTER_SKIP on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_ALL on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_ELEMENT on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_ATTRIBUTE on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_TEXT on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_CDATA_SECTION on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_ENTITY_REFERENCE on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_ENTITY on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_PROCESSING_INSTRUCTION on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_COMMENT on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_DOCUMENT on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_DOCUMENT_TYPE on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_DOCUMENT_FRAGMENT on interface prototype object": true,
|
||||
"NodeFilter interface: constant SHOW_NOTATION on interface prototype object": true,
|
||||
"NodeFilter interface: operation acceptNode(Node)": true,
|
||||
"DOMStringList interface: existence and properties of interface object": true,
|
||||
"DOMStringList interface: existence and properties of interface prototype object": true,
|
||||
"DOMStringList interface: existence and properties of interface prototype object's \"constructor\" property": true,
|
||||
"DOMStringList interface: attribute length": true
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"before\" with the proper type (9)": true,
|
||||
"CharacterData interface: calling before(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"after\" with the proper type (10)": true,
|
||||
"CharacterData interface: calling after(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
|
||||
"CharacterData interface: calling replace(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"remove\" with the proper type (12)": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"before\" with the proper type (9)": true,
|
||||
"CharacterData interface: calling before(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"after\" with the proper type (10)": true,
|
||||
"CharacterData interface: calling after(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"replace\" with the proper type (11)": true,
|
||||
"CharacterData interface: calling replace(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"remove\" with the proper type (12)": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"before\" with the proper type (9)": true,
|
||||
"CharacterData interface: calling before(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"after\" with the proper type (10)": true,
|
||||
"CharacterData interface: calling after(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
|
||||
"CharacterData interface: calling replace(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
|
||||
"CharacterData interface: document.createComment(\"abc\") must inherit property \"remove\" with the proper type (12)": true,
|
||||
"NodeFilter interface: existence and properties of interface object": true,
|
||||
"NodeList interface: existence and properties of interface prototype object": true
|
||||
}
|
||||
|
|
|
@ -11,18 +11,11 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MOCHITEST_FILES := \
|
||||
test_CharacterData-remove.html.json \
|
||||
test_DOMImplementation-createDocument.html.json \
|
||||
test_DOMImplementation-createHTMLDocument.html.json \
|
||||
test_Document-createElementNS.html.json \
|
||||
test_Document-getElementsByTagName.html.json \
|
||||
test_DocumentType-remove.html.json \
|
||||
test_Element-remove.html.json \
|
||||
test_Node-isEqualNode.xhtml.json \
|
||||
test_NodeFilter-constants.html.json \
|
||||
test_Range-attributes.html.json \
|
||||
test_Range-commonAncestorContainer.html.json \
|
||||
test_Range-comparePoint.html.json \
|
||||
test_Range-detach.html.json \
|
||||
test_attributes.html.json \
|
||||
test_case.html.json \
|
||||
test_historical.html.json \
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"CharacterData.remove": true,
|
||||
"CharacterData.remove 1": true,
|
||||
"CharacterData.remove 2": true
|
||||
"text should support remove()": true,
|
||||
"remove() should work if text doesn't have a parent": true,
|
||||
"remove() should work if text does have a parent": true,
|
||||
"remove() should work if text does have a parent and siblings": true,
|
||||
"comment should support remove()": true,
|
||||
"remove() should work if comment doesn't have a parent": true,
|
||||
"remove() should work if comment does have a parent": true,
|
||||
"remove() should work if comment does have a parent and siblings": true,
|
||||
"PI should support remove()": true,
|
||||
"remove() should work if PI doesn't have a parent": true,
|
||||
"remove() should work if PI does have a parent": true,
|
||||
"remove() should work if PI does have a parent and siblings": true
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Missing title argument": true
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"Document.getElementsByTagName 2": true,
|
||||
"Document.getElementsByTagName 3": true
|
||||
"Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)": true,
|
||||
"Document.getElementsByTagName 1": true,
|
||||
"Document.getElementsByTagName 2": true
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
"DocumentType.remove": true
|
||||
"doctype should support remove()": true,
|
||||
"remove() should work if doctype doesn't have a parent": true,
|
||||
"remove() should work if doctype does have a parent": true,
|
||||
"remove() should work if doctype does have a parent and siblings": true
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
{
|
||||
"Element.remove": true
|
||||
"element should support remove()": true,
|
||||
"remove() should work if element doesn't have a parent": true,
|
||||
"remove() should work if element does have a parent": true,
|
||||
"remove() should work if element does have a parent and siblings": true
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Range attributes": true
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Detached Range": true
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Range.comparePoint": true
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Range.detach": true
|
||||
}
|
|
@ -303,6 +303,10 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls)
|
|||
// TODO
|
||||
break;
|
||||
|
||||
case "callback":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";
|
||||
}
|
||||
|
@ -1029,18 +1033,42 @@ IdlException.prototype.test_object = function(desc)
|
|||
/// IdlInterface ///
|
||||
function IdlInterface(obj) { IdlExceptionOrInterface.call(this, obj); }
|
||||
IdlInterface.prototype = Object.create(IdlExceptionOrInterface.prototype);
|
||||
IdlInterface.prototype.is_callback = function()
|
||||
//@{
|
||||
{
|
||||
return this.has_extended_attribute("Callback");
|
||||
}
|
||||
//@}
|
||||
|
||||
IdlInterface.prototype.has_constants = function()
|
||||
//@{
|
||||
{
|
||||
return this.members.some(function(member) {
|
||||
return member.type === "const";
|
||||
});
|
||||
}
|
||||
//@}
|
||||
|
||||
IdlInterface.prototype.test_self = function()
|
||||
//@{
|
||||
{
|
||||
test(function()
|
||||
{
|
||||
// "For every interface that is not declared with the
|
||||
// [NoInterfaceObject] extended attribute, a corresponding property
|
||||
// must exist on the interface’s relevant namespace object. The name of
|
||||
// the property is the identifier of the interface, and its value is an
|
||||
// object called the interface object. The property has the attributes
|
||||
// { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true
|
||||
// }."
|
||||
// This function tests WebIDL as of 2012-11-28.
|
||||
|
||||
// "For every interface that:
|
||||
// * is a callback interface that has constants declared on it, or
|
||||
// * is a non-callback interface that is not declared with the
|
||||
// [NoInterfaceObject] extended attribute,
|
||||
// a corresponding property MUST exist on the ECMAScript global object.
|
||||
// The name of the property is the identifier of the interface, and its
|
||||
// value is an object called the interface object.
|
||||
// The property has the attributes { [[Writable]]: true,
|
||||
// [[Enumerable]]: false, [[Configurable]]: true }."
|
||||
if (this.is_callback() && !this.has_constants()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Should we test here that the property is actually writable
|
||||
// etc., or trust getOwnPropertyDescriptor?
|
||||
assert_own_property(window, this.name,
|
||||
|
@ -1052,43 +1080,53 @@ IdlInterface.prototype.test_self = function()
|
|||
assert_false(desc.enumerable, "window's property " + format_value(this.name) + " is enumerable");
|
||||
assert_true(desc.configurable, "window's property " + format_value(this.name) + " is not configurable");
|
||||
|
||||
// "Interface objects are always function objects."
|
||||
if (this.is_callback()) {
|
||||
// "The internal [[Prototype]] property of an interface object for
|
||||
// a callback interface MUST be the Object.prototype object."
|
||||
assert_equals(Object.getPrototypeOf(window[this.name]), Object.prototype,
|
||||
"prototype of window's property " + format_value(this.name) + " is not Object.prototype");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// "The interface object for a given non-callback interface is a
|
||||
// function object."
|
||||
// "If an object is defined to be a function object, then it has
|
||||
// characteristics as follows:"
|
||||
// "Its [[Prototype]] internal property is the Function prototype
|
||||
// object."
|
||||
// Note: This doesn't match browsers as of December 2011, see
|
||||
// http://www.w3.org/Bugs/Public/show_bug.cgi?id=14813
|
||||
|
||||
// "* Its [[Prototype]] internal property is the Function prototype
|
||||
// object."
|
||||
assert_equals(Object.getPrototypeOf(window[this.name]), Function.prototype,
|
||||
"prototype of window's property " + format_value(this.name) + " is not Function.prototype");
|
||||
// "Its [[Get]] internal property is set as described in ECMA-262
|
||||
// section 15.3.5.4."
|
||||
|
||||
// "* Its [[Get]] internal property is set as described in ECMA-262
|
||||
// section 15.3.5.4."
|
||||
// Not much to test for this.
|
||||
// "Its [[Construct]] internal property is set as described in ECMA-262
|
||||
// section 13.2.2."
|
||||
|
||||
// "* Its [[Construct]] internal property is set as described in
|
||||
// ECMA-262 section 13.2.2."
|
||||
// Tested below if no constructor is defined. TODO: test constructors
|
||||
// if defined.
|
||||
// "Its [[HasInstance]] internal property is set as described in
|
||||
// ECMA-262 section 15.3.5.3, unless otherwise specified."
|
||||
|
||||
// "* Its [[HasInstance]] internal property is set as described in
|
||||
// ECMA-262 section 15.3.5.3, unless otherwise specified."
|
||||
// TODO
|
||||
// "Its [[Class]] internal property is “Function”."
|
||||
|
||||
// "* Its [[NativeBrand]] internal property is “Function”."
|
||||
// String() returns something implementation-dependent, because it calls
|
||||
// Function#toString.
|
||||
assert_class_string(window[this.name], "Function", "class string of " + this.name);
|
||||
|
||||
if (!this.has_extended_attribute("Constructor"))
|
||||
{
|
||||
if (!this.has_extended_attribute("Constructor")) {
|
||||
// "The internal [[Call]] method of the interface object behaves as
|
||||
// follows . . .
|
||||
//
|
||||
// "If I was not declared with a [Constructor] extended attribute,
|
||||
// then throw a TypeError."
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
assert_throws(new TypeError(), function() {
|
||||
window[this.name]();
|
||||
}.bind(this), "interface object didn't throw TypeError when called as a function");
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
assert_throws(new TypeError(), function() {
|
||||
new window[this.name]();
|
||||
}.bind(this), "interface object didn't throw TypeError when called as a constructor");
|
||||
}
|
||||
|
@ -1138,6 +1176,12 @@ IdlInterface.prototype.test_self = function()
|
|||
assert_own_property(window, this.name,
|
||||
"window does not have own property " + format_value(this.name));
|
||||
|
||||
if (this.has_extended_attribute("Callback")) {
|
||||
assert_false("prototype" in window[this.name],
|
||||
this.name + ' should not have a "prototype" property');
|
||||
return;
|
||||
}
|
||||
|
||||
// "The interface object must also have a property named “prototype”
|
||||
// with attributes { [[Writable]]: false, [[Enumerable]]: false,
|
||||
// [[Configurable]]: false } whose value is an object called the
|
||||
|
@ -1219,6 +1263,13 @@ IdlInterface.prototype.test_self = function()
|
|||
{
|
||||
assert_own_property(window, this.name,
|
||||
"window does not have own property " + format_value(this.name));
|
||||
|
||||
if (this.has_extended_attribute("Callback")) {
|
||||
assert_false("prototype" in window[this.name],
|
||||
this.name + ' should not have a "prototype" property');
|
||||
return;
|
||||
}
|
||||
|
||||
assert_own_property(window[this.name], "prototype",
|
||||
'interface "' + this.name + '" does not have own property "prototype"');
|
||||
|
||||
|
@ -1282,6 +1333,13 @@ IdlInterface.prototype.test_members = function()
|
|||
{
|
||||
assert_own_property(window, this.name,
|
||||
"window does not have own property " + format_value(this.name));
|
||||
|
||||
if (this.has_extended_attribute("Callback")) {
|
||||
assert_false("prototype" in window[this.name],
|
||||
this.name + ' should not have a "prototype" property');
|
||||
return;
|
||||
}
|
||||
|
||||
assert_own_property(window[this.name], "prototype",
|
||||
'interface "' + this.name + '" does not have own property "prototype"');
|
||||
|
||||
|
@ -1331,6 +1389,13 @@ IdlInterface.prototype.test_members = function()
|
|||
{
|
||||
assert_own_property(window, this.name,
|
||||
"window does not have own property " + format_value(this.name));
|
||||
|
||||
if (this.has_extended_attribute("Callback")) {
|
||||
assert_false("prototype" in window[this.name],
|
||||
this.name + ' should not have a "prototype" property');
|
||||
return;
|
||||
}
|
||||
|
||||
assert_own_property(window[this.name], "prototype",
|
||||
'interface "' + this.name + '" does not have own property "prototype"');
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ policies and contribution forms [3].
|
|||
* author - Name and contact information for the author of the test in the
|
||||
* format: "Name <email_addr>" or "Name http://contact/url"
|
||||
*
|
||||
* flags - space separated list of test flags in addition to any present in
|
||||
* the head metadata
|
||||
*
|
||||
* == Asynchronous Tests ==
|
||||
*
|
||||
* Testing asynchronous features is somewhat more complex since the result of
|
||||
|
@ -94,6 +97,19 @@ policies and contribution forms [3].
|
|||
*
|
||||
* t.done();
|
||||
*
|
||||
* As a convenience, async_test can also takes a function as first argument.
|
||||
* This function is called with the test object as both its `this` object and
|
||||
* first argument. The above example can be rewritten as:
|
||||
*
|
||||
* async_test(function(t) {
|
||||
* object.some_event = function() {
|
||||
* t.step(function (){assert_true(true); t.done();});
|
||||
* };
|
||||
* }, "Simple async test");
|
||||
*
|
||||
* which avoids cluttering the global scope with references to async
|
||||
* tests instances.
|
||||
*
|
||||
* The properties argument is identical to that for test().
|
||||
*
|
||||
* In many cases it is convenient to run a step in response to an event or a
|
||||
|
@ -222,7 +238,7 @@ policies and contribution forms [3].
|
|||
*
|
||||
* In order to collect the results of multiple pages containing tests, the test
|
||||
* harness will, when loaded in a nested browsing context, attempt to call
|
||||
* certain functions in each ancestor browsing context:
|
||||
* certain functions in each ancestor and opener browsing context:
|
||||
*
|
||||
* start - start_callback
|
||||
* result - result_callback
|
||||
|
@ -231,6 +247,22 @@ policies and contribution forms [3].
|
|||
* These are given the same arguments as the corresponding internal callbacks
|
||||
* described above.
|
||||
*
|
||||
* == External API through cross-document messaging ==
|
||||
*
|
||||
* Where supported, the test harness will also send messages using
|
||||
* cross-document messaging to each ancestor and opener browsing context. Since
|
||||
* it uses the wildcard keyword (*), cross-origin communication is enabled and
|
||||
* script on different origins can collect the results.
|
||||
*
|
||||
* This API follows similar conventions as those described above only slightly
|
||||
* modified to accommodate message event API. Each message is sent by the harness
|
||||
* is passed a single vanilla object, available as the `data` property of the
|
||||
* event object. These objects are structures as follows:
|
||||
*
|
||||
* start - { type: "start" }
|
||||
* result - { type: "result", test: Test }
|
||||
* complete - { type: "complete", tests: [Test, ...], status: TestsStatus }
|
||||
*
|
||||
* == List of assertions ==
|
||||
*
|
||||
* assert_true(actual, description)
|
||||
|
@ -376,11 +408,19 @@ policies and contribution forms [3].
|
|||
}
|
||||
}
|
||||
|
||||
function async_test(name, properties)
|
||||
function async_test(func, name, properties)
|
||||
{
|
||||
if (typeof func !== "function") {
|
||||
properties = name;
|
||||
name = func;
|
||||
func = null;
|
||||
}
|
||||
var test_name = name ? name : next_default_name();
|
||||
properties = properties ? properties : {};
|
||||
var test_obj = new Test(test_name, properties);
|
||||
if (func) {
|
||||
test_obj.step(func, test_obj, test_obj);
|
||||
}
|
||||
return test_obj;
|
||||
}
|
||||
|
||||
|
@ -652,7 +692,7 @@ policies and contribution forms [3].
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(actual[p] === expected[p], "assert_object_equals", description,
|
||||
assert(same_value(actual[p], expected[p]), "assert_object_equals", description,
|
||||
"property ${p} expected ${expected} got ${actual}",
|
||||
{p:p, expected:expected, actual:actual});
|
||||
}
|
||||
|
@ -683,7 +723,7 @@ policies and contribution forms [3].
|
|||
"property ${i}, property expected to be $expected but was $actual",
|
||||
{i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing",
|
||||
actual:actual.hasOwnProperty(i) ? "present" : "missing"});
|
||||
assert(expected[i] === actual[i],
|
||||
assert(same_value(expected[i], actual[i]),
|
||||
"assert_array_equals", description,
|
||||
"property ${i}, expected ${expected} but got ${actual}",
|
||||
{i:i, expected:expected[i], actual:actual[i]});
|
||||
|
@ -777,7 +817,7 @@ policies and contribution forms [3].
|
|||
//Note that this can have side effects in the case where
|
||||
//the property has PutForwards
|
||||
object[property_name] = initial_value + "a"; //XXX use some other value here?
|
||||
assert(object[property_name] === initial_value,
|
||||
assert(same_value(object[property_name], initial_value),
|
||||
"assert_readonly", description,
|
||||
"changing property ${p} succeeded",
|
||||
{p:property_name});
|
||||
|
@ -838,7 +878,7 @@ policies and contribution forms [3].
|
|||
QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
|
||||
TIMEOUT_ERR: 'TimeoutError',
|
||||
INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
|
||||
DATA_CLONE_ERR: 'DataCloneError',
|
||||
DATA_CLONE_ERR: 'DataCloneError'
|
||||
};
|
||||
|
||||
var name = code in code_name_map ? code_name_map[code] : code;
|
||||
|
@ -871,7 +911,7 @@ policies and contribution forms [3].
|
|||
DataError: 0,
|
||||
TransactionInactiveError: 0,
|
||||
ReadOnlyError: 0,
|
||||
VersionError: 0,
|
||||
VersionError: 0
|
||||
};
|
||||
|
||||
if (!(name in name_code_map))
|
||||
|
@ -954,13 +994,29 @@ policies and contribution forms [3].
|
|||
tests.push(this);
|
||||
}
|
||||
|
||||
Test.prototype = {
|
||||
Test.statuses = {
|
||||
PASS:0,
|
||||
FAIL:1,
|
||||
TIMEOUT:2,
|
||||
NOTRUN:3
|
||||
};
|
||||
|
||||
Test.prototype = merge({}, Test.statuses);
|
||||
|
||||
Test.prototype.structured_clone = function()
|
||||
{
|
||||
if(!this._structured_clone)
|
||||
{
|
||||
var msg = this.message;
|
||||
msg = msg ? String(msg) : msg;
|
||||
this._structured_clone = merge({
|
||||
name:String(this.name),
|
||||
status:this.status,
|
||||
message:msg
|
||||
}, Test.statuses);
|
||||
}
|
||||
return this._structured_clone;
|
||||
};
|
||||
|
||||
Test.prototype.step = function(func, this_obj)
|
||||
{
|
||||
|
@ -1085,12 +1141,29 @@ policies and contribution forms [3].
|
|||
this.status = null;
|
||||
this.message = null;
|
||||
}
|
||||
TestsStatus.prototype = {
|
||||
|
||||
TestsStatus.statuses = {
|
||||
OK:0,
|
||||
ERROR:1,
|
||||
TIMEOUT:2
|
||||
};
|
||||
|
||||
TestsStatus.prototype = merge({}, TestsStatus.statuses);
|
||||
|
||||
TestsStatus.prototype.structured_clone = function()
|
||||
{
|
||||
if(!this._structured_clone)
|
||||
{
|
||||
var msg = this.message;
|
||||
msg = msg ? String(msg) : msg;
|
||||
this._structured_clone = merge({
|
||||
status:this.status,
|
||||
message:msg
|
||||
}, TestsStatus.statuses);
|
||||
}
|
||||
return this._structured_clone;
|
||||
};
|
||||
|
||||
function Tests()
|
||||
{
|
||||
this.tests = [];
|
||||
|
@ -1232,10 +1305,10 @@ policies and contribution forms [3].
|
|||
{
|
||||
callback(this_obj.properties);
|
||||
});
|
||||
forEach(ancestor_windows(),
|
||||
function(w)
|
||||
forEach_windows(
|
||||
function(w, is_same_origin)
|
||||
{
|
||||
if(w.start_callback)
|
||||
if(is_same_origin && w.start_callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1249,6 +1322,13 @@ policies and contribution forms [3].
|
|||
}
|
||||
}
|
||||
}
|
||||
if (supports_post_message(w) && w !== self)
|
||||
{
|
||||
w.postMessage({
|
||||
type: "start",
|
||||
properties: this_obj.properties
|
||||
}, "*");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1272,10 +1352,10 @@ policies and contribution forms [3].
|
|||
callback(test, this_obj);
|
||||
});
|
||||
|
||||
forEach(ancestor_windows(),
|
||||
function(w)
|
||||
forEach_windows(
|
||||
function(w, is_same_origin)
|
||||
{
|
||||
if(w.result_callback)
|
||||
if(is_same_origin && w.result_callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1288,6 +1368,13 @@ policies and contribution forms [3].
|
|||
}
|
||||
}
|
||||
}
|
||||
if (supports_post_message(w) && w !== self)
|
||||
{
|
||||
w.postMessage({
|
||||
type: "result",
|
||||
test: test.structured_clone()
|
||||
}, "*");
|
||||
}
|
||||
});
|
||||
this.processing_callbacks = false;
|
||||
if (this_obj.all_done())
|
||||
|
@ -1318,6 +1405,11 @@ policies and contribution forms [3].
|
|||
{
|
||||
clearTimeout(this.timeout_id);
|
||||
var this_obj = this;
|
||||
var tests = map(this_obj.tests,
|
||||
function(test)
|
||||
{
|
||||
return test.structured_clone();
|
||||
});
|
||||
if (this.status.status === null)
|
||||
{
|
||||
this.status.status = this.status.OK;
|
||||
|
@ -1329,10 +1421,10 @@ policies and contribution forms [3].
|
|||
callback(this_obj.tests, this_obj.status);
|
||||
});
|
||||
|
||||
forEach(ancestor_windows(),
|
||||
function(w)
|
||||
forEach_windows(
|
||||
function(w, is_same_origin)
|
||||
{
|
||||
if(w.completion_callback)
|
||||
if(is_same_origin && w.completion_callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1346,6 +1438,14 @@ policies and contribution forms [3].
|
|||
}
|
||||
}
|
||||
}
|
||||
if (supports_post_message(w) && w !== self)
|
||||
{
|
||||
w.postMessage({
|
||||
type: "complete",
|
||||
tests: tests,
|
||||
status: this_obj.status.structured_clone()
|
||||
}, "*");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1382,7 +1482,7 @@ policies and contribution forms [3].
|
|||
*/
|
||||
|
||||
function Output() {
|
||||
this.output_document = null;
|
||||
this.output_document = document;
|
||||
this.output_node = null;
|
||||
this.done_count = 0;
|
||||
this.enabled = settings.output;
|
||||
|
@ -1939,22 +2039,107 @@ policies and contribution forms [3].
|
|||
target[components[components.length - 1]] = object;
|
||||
}
|
||||
|
||||
function ancestor_windows() {
|
||||
//Get the windows [self ... top] as an array
|
||||
if ("result_cache" in ancestor_windows)
|
||||
{
|
||||
return ancestor_windows.result_cache;
|
||||
}
|
||||
var rv = [self];
|
||||
var w = self;
|
||||
while (w != w.parent)
|
||||
{
|
||||
w = w.parent;
|
||||
rv.push(w);
|
||||
}
|
||||
ancestor_windows.result_cache = rv;
|
||||
return rv;
|
||||
}
|
||||
function forEach_windows(callback) {
|
||||
// Iterate of the the windows [self ... top, opener]. The callback is passed
|
||||
// two objects, the first one is the windows object itself, the second one
|
||||
// is a boolean indicating whether or not its on the same origin as the
|
||||
// current window.
|
||||
var cache = forEach_windows.result_cache;
|
||||
if (!cache) {
|
||||
cache = [[self, true]];
|
||||
var w = self;
|
||||
var i = 0;
|
||||
var so;
|
||||
var origins = location.ancestorOrigins;
|
||||
while (w != w.parent)
|
||||
{
|
||||
w = w.parent;
|
||||
// In WebKit, calls to parent windows' properties that aren't on the same
|
||||
// origin cause an error message to be displayed in the error console but
|
||||
// don't throw an exception. This is a deviation from the current HTML5
|
||||
// spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
|
||||
// The problem with WebKit's behavior is that it pollutes the error console
|
||||
// with error messages that can't be caught.
|
||||
//
|
||||
// This issue can be mitigated by relying on the (for now) proprietary
|
||||
// `location.ancestorOrigins` property which returns an ordered list of
|
||||
// the origins of enclosing windows. See:
|
||||
// http://trac.webkit.org/changeset/113945.
|
||||
if(origins) {
|
||||
so = (location.origin == origins[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
so = is_same_origin(w);
|
||||
}
|
||||
cache.push([w, so]);
|
||||
i++;
|
||||
}
|
||||
w = window.opener;
|
||||
if(w)
|
||||
{
|
||||
// window.opener isn't included in the `location.ancestorOrigins` prop.
|
||||
// We'll just have to deal with a simple check and an error msg on WebKit
|
||||
// browsers in this case.
|
||||
cache.push([w, is_same_origin(w)]);
|
||||
}
|
||||
forEach_windows.result_cache = cache;
|
||||
}
|
||||
|
||||
forEach(cache,
|
||||
function(a)
|
||||
{
|
||||
callback.apply(null, a);
|
||||
});
|
||||
}
|
||||
|
||||
function is_same_origin(w) {
|
||||
try {
|
||||
'random_prop' in w;
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function supports_post_message(w)
|
||||
{
|
||||
var supports;
|
||||
var type;
|
||||
// Given IE implements postMessage across nested iframes but not across
|
||||
// windows or tabs, you can't infer cross-origin communication from the presence
|
||||
// of postMessage on the current window object only.
|
||||
//
|
||||
// Touching the postMessage prop on a window can throw if the window is
|
||||
// not from the same origin AND post message is not supported in that
|
||||
// browser. So just doing an existence test here won't do, you also need
|
||||
// to wrap it in a try..cacth block.
|
||||
try
|
||||
{
|
||||
type = typeof w.postMessage;
|
||||
if (type === "function")
|
||||
{
|
||||
supports = true;
|
||||
}
|
||||
// IE8 supports postMessage, but implements it as a host object which
|
||||
// returns "object" as its `typeof`.
|
||||
else if (type === "object")
|
||||
{
|
||||
supports = true;
|
||||
}
|
||||
// This is the case where postMessage isn't supported AND accessing a
|
||||
// window property across origins does NOT throw (e.g. old Safari browser).
|
||||
else
|
||||
{
|
||||
supports = false;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
// This is the case where postMessage isn't supported AND accessing a
|
||||
// window property across origins throws (e.g. old Firefox browser).
|
||||
supports = false;
|
||||
}
|
||||
return supports;
|
||||
}
|
||||
})();
|
||||
// vim: set expandtab shiftwidth=4 tabstop=4:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
# THIS FILE IS AUTOGENERATED BY importTestSuites.py - DO NOT EDIT
|
||||
|
||||
DIRS += [
|
||||
'webapps/DOMCore/tests/approved',
|
||||
|
|
|
@ -23,7 +23,7 @@ exception DOMException {
|
|||
const unsigned short NAMESPACE_ERR = 14;
|
||||
const unsigned short INVALID_ACCESS_ERR = 15;
|
||||
const unsigned short VALIDATION_ERR = 16; // historical
|
||||
const unsigned short TYPE_MISMATCH_ERR = 17;
|
||||
const unsigned short TYPE_MISMATCH_ERR = 17; // historical; use TypeError instead
|
||||
const unsigned short SECURITY_ERR = 18;
|
||||
const unsigned short NETWORK_ERR = 19;
|
||||
const unsigned short ABORT_ERR = 20;
|
||||
|
@ -35,6 +35,7 @@ exception DOMException {
|
|||
unsigned short code;
|
||||
};
|
||||
|
||||
[Constructor(DOMString name)]
|
||||
interface DOMError {
|
||||
readonly attribute DOMString name;
|
||||
};
|
||||
|
@ -45,6 +46,7 @@ interface Event {
|
|||
readonly attribute EventTarget? target;
|
||||
readonly attribute EventTarget? currentTarget;
|
||||
|
||||
const unsigned short NONE = 0;
|
||||
const unsigned short CAPTURING_PHASE = 1;
|
||||
const unsigned short AT_TARGET = 2;
|
||||
const unsigned short BUBBLING_PHASE = 3;
|
||||
|
@ -58,29 +60,31 @@ interface Event {
|
|||
void preventDefault();
|
||||
readonly attribute boolean defaultPrevented;
|
||||
|
||||
readonly attribute boolean isTrusted;
|
||||
[Unforgeable] readonly attribute boolean isTrusted;
|
||||
readonly attribute DOMTimeStamp timeStamp;
|
||||
|
||||
void initEvent(DOMString type, boolean bubbles, boolean cancelable);
|
||||
};
|
||||
|
||||
dictionary EventInit {
|
||||
boolean bubbles;
|
||||
boolean cancelable;
|
||||
boolean bubbles = false;
|
||||
boolean cancelable = false;
|
||||
};
|
||||
|
||||
[Constructor(DOMString type, optional CustomEventInit eventInitDict)]
|
||||
interface CustomEvent : Event {
|
||||
readonly attribute any detail;
|
||||
|
||||
void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any details);
|
||||
};
|
||||
|
||||
dictionary CustomEventInit : EventInit {
|
||||
any detail;
|
||||
any detail = null;
|
||||
};
|
||||
|
||||
interface EventTarget {
|
||||
void addEventListener(DOMString type, EventListener? listener, optional boolean capture);
|
||||
void removeEventListener(DOMString type, EventListener? listener, optional boolean capture);
|
||||
void addEventListener(DOMString type, EventListener? callback, optional boolean capture);
|
||||
void removeEventListener(DOMString type, EventListener? callback, optional boolean capture);
|
||||
boolean dispatchEvent(Event event);
|
||||
};
|
||||
|
||||
|
@ -89,71 +93,63 @@ interface EventListener {
|
|||
void handleEvent(Event event);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface ParentNode {
|
||||
readonly attribute HTMLCollection children;
|
||||
readonly attribute Element? firstElementChild;
|
||||
readonly attribute Element? lastElementChild;
|
||||
readonly attribute unsigned long childElementCount;
|
||||
|
||||
void prepend((Node or DOMString)... nodes);
|
||||
void append((Node or DOMString)... nodes);
|
||||
};
|
||||
Document implements ParentNode;
|
||||
DocumentFragment implements ParentNode;
|
||||
Element implements ParentNode;
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface ChildNode {
|
||||
readonly attribute Element? previousElementSibling;
|
||||
readonly attribute Element? nextElementSibling;
|
||||
|
||||
void before((Node or DOMString)... nodes);
|
||||
void after((Node or DOMString)... nodes);
|
||||
void replace((Node or DOMString)... nodes);
|
||||
void remove();
|
||||
};
|
||||
DocumentType implements ChildNode;
|
||||
Element implements ChildNode;
|
||||
CharacterData implements ChildNode;
|
||||
|
||||
[Constructor(MutationCallback callback)]
|
||||
interface MutationObserver {
|
||||
void observe(Node target, optional MutationObserverInit options);
|
||||
void observe(Node target, MutationObserverInit options);
|
||||
void disconnect();
|
||||
sequence<MutationRecord> takeRecords();
|
||||
};
|
||||
|
||||
[Callback]
|
||||
interface MutationCallback {
|
||||
void handleEvent(MutationRecord[] mutations, MutationObserver observer);
|
||||
};
|
||||
callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);
|
||||
|
||||
dictionary MutationObserverInit {
|
||||
// Mutation types
|
||||
boolean childList; // If true, mutations affecting node’s childNodes are included.
|
||||
boolean attributes; // If true, mutations affecting element’s attributes are included.
|
||||
boolean characterData; // If true, mutations affecting the value of CharacterData nodes are included.
|
||||
// [Note: If none of the known mutation types is specified, an Error is thrown]
|
||||
|
||||
// Subtree observation
|
||||
boolean subtree; // If true, the observed set of nodes for this registration should include
|
||||
// descendants of MutationTarget (behavior described below).
|
||||
|
||||
// Old values
|
||||
boolean attributeOldValue;
|
||||
// If true, MutationRecords describing changes to attributes should
|
||||
// contain the value of the attribute before the change. If true
|
||||
// without attribute: true specified, an Error is thrown.
|
||||
|
||||
boolean characterDataOldValue;
|
||||
// If true, MutationRecords describing changes to
|
||||
// CharacterData nodes should contain the value
|
||||
// of the node before the change. If true without
|
||||
// characterData: true, an Error is thrown.
|
||||
|
||||
// Filtering
|
||||
DOMString[] attributeFilter;
|
||||
// If provided, only changes to attributes with localName equaling
|
||||
// one of the provided strings will be delivered. If provided without
|
||||
// attribute: true, an Error is thrown.
|
||||
boolean childList = false;
|
||||
boolean attributes = false;
|
||||
boolean characterData = false;
|
||||
boolean subtree = false;
|
||||
boolean attributeOldValue = false;
|
||||
boolean characterDataOldValue = false;
|
||||
sequence<DOMString> attributeFilter;
|
||||
};
|
||||
|
||||
interface MutationRecord {
|
||||
// Mutation type: one of 'childList', 'attributes', or 'characterData'
|
||||
readonly attribute DOMString type;
|
||||
|
||||
// For childList and attributes, target is the owner node affected.
|
||||
// For CharacterData, target is the node affected.
|
||||
readonly attribute Node target;
|
||||
|
||||
// For type == 'childList', Sequence of added and removed nodes in this operation.
|
||||
readonly attribute NodeList addedNodes;
|
||||
readonly attribute NodeList removedNodes;
|
||||
|
||||
// For type == 'childList', The siblings in childNodes immediately preceding following the first
|
||||
// and last nodes added and/or removed.
|
||||
readonly attribute Node previousSibling;
|
||||
readonly attribute Node nextSibling;
|
||||
|
||||
// For type == 'attribute', the name and namespaceURI of the attribute affected
|
||||
readonly attribute DOMString attributeName;
|
||||
readonly attribute DOMString attributeNamespace;
|
||||
|
||||
// For type == 'attribute' or 'characterData', if requested, the value immediately
|
||||
// preceding the mutation.
|
||||
readonly attribute DOMString oldValue;
|
||||
readonly attribute Node? previousSibling;
|
||||
readonly attribute Node? nextSibling;
|
||||
readonly attribute DOMString? attributeName;
|
||||
readonly attribute DOMString? attributeNamespace;
|
||||
readonly attribute DOMString? oldValue;
|
||||
};
|
||||
|
||||
interface Node : EventTarget {
|
||||
|
@ -184,29 +180,30 @@ interface Node : EventTarget {
|
|||
readonly attribute Node? previousSibling;
|
||||
readonly attribute Node? nextSibling;
|
||||
|
||||
const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
|
||||
const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
|
||||
const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
|
||||
const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; // historical
|
||||
unsigned short compareDocumentPosition(Node other);
|
||||
boolean contains(Node? other);
|
||||
|
||||
attribute DOMString? nodeValue;
|
||||
attribute DOMString? textContent;
|
||||
Node insertBefore(Node node, Node? child);
|
||||
Node appendChild(Node node);
|
||||
Node replaceChild(Node node, Node child);
|
||||
Node removeChild(Node child);
|
||||
void normalize();
|
||||
|
||||
Node cloneNode(optional boolean deep);
|
||||
boolean isEqualNode(Node? node);
|
||||
|
||||
DOMString lookupPrefix(DOMString? namespace);
|
||||
DOMString lookupNamespaceURI(DOMString? prefix);
|
||||
const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
|
||||
const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
|
||||
const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
|
||||
const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
|
||||
const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
|
||||
unsigned short compareDocumentPosition(Node other);
|
||||
boolean contains(Node? other);
|
||||
|
||||
DOMString? lookupPrefix(DOMString? namespace);
|
||||
DOMString? lookupNamespaceURI(DOMString? prefix);
|
||||
boolean isDefaultNamespace(DOMString? namespace);
|
||||
|
||||
Node insertBefore(Node node, Node? child);
|
||||
Node appendChild(Node node);
|
||||
Node replaceChild(Node node, Node child);
|
||||
Node removeChild(Node child);
|
||||
};
|
||||
|
||||
[Constructor]
|
||||
|
@ -220,9 +217,9 @@ interface Document : Node {
|
|||
|
||||
readonly attribute DocumentType? doctype;
|
||||
readonly attribute Element? documentElement;
|
||||
NodeList getElementsByTagName(DOMString qualifiedName);
|
||||
NodeList getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
||||
NodeList getElementsByClassName(DOMString classNames);
|
||||
HTMLCollection getElementsByTagName(DOMString localName);
|
||||
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
||||
HTMLCollection getElementsByClassName(DOMString classNames);
|
||||
Element? getElementById(DOMString elementId);
|
||||
|
||||
Element createElement(DOMString localName);
|
||||
|
@ -235,47 +232,33 @@ interface Document : Node {
|
|||
Node importNode(Node node, optional boolean deep);
|
||||
Node adoptNode(Node node);
|
||||
|
||||
Event createEvent(DOMString eventInterfaceName);
|
||||
Event createEvent(DOMString interface);
|
||||
|
||||
Range createRange();
|
||||
|
||||
// NodeFilter.SHOW_ALL = 0xFFFFFFFF
|
||||
NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow, optional NodeFilter? filter);
|
||||
TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow, optional NodeFilter? filter);
|
||||
|
||||
// NEW
|
||||
// Invalid WebIDL https://www.w3.org/Bugs/Public/show_bug.cgi?id=15346
|
||||
//void prepend((Node or DOMString)... nodes);
|
||||
//void append((Node or DOMString)... nodes);
|
||||
};
|
||||
|
||||
interface XMLDocument : Document {};
|
||||
|
||||
interface DOMImplementation {
|
||||
boolean hasFeature(DOMString feature, [TreatNullAs=EmptyString] DOMString version);
|
||||
|
||||
DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
|
||||
XMLDocument createDocument(DOMString? namespace, DOMString qualifiedName, DocumentType? doctype);
|
||||
Document createHTMLDocument(DOMString title);
|
||||
XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, DocumentType? doctype);
|
||||
Document createHTMLDocument(optional DOMString title);
|
||||
|
||||
boolean hasFeature(DOMString feature, [TreatNullAs=EmptyString] DOMString version);
|
||||
};
|
||||
|
||||
[Constructor]
|
||||
interface DocumentFragment : Node {
|
||||
// NEW
|
||||
// Invalid WebIDL https://www.w3.org/Bugs/Public/show_bug.cgi?id=15346
|
||||
//void prepend((Node or DOMString)... nodes);
|
||||
//void append((Node or DOMString)... nodes);
|
||||
};
|
||||
|
||||
interface DocumentType : Node {
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString publicId;
|
||||
readonly attribute DOMString systemId;
|
||||
|
||||
// NEW
|
||||
// Invalid WebIDL https://www.w3.org/Bugs/Public/show_bug.cgi?id=15346
|
||||
//void before((Node or DOMString)... nodes);
|
||||
//void after((Node or DOMString)... nodes);
|
||||
//void replace((Node or DOMString)... nodes);
|
||||
void remove();
|
||||
};
|
||||
|
||||
interface Element : Node {
|
||||
|
@ -298,34 +281,18 @@ interface Element : Node {
|
|||
boolean hasAttribute(DOMString name);
|
||||
boolean hasAttributeNS(DOMString? namespace, DOMString localName);
|
||||
|
||||
NodeList getElementsByTagName(DOMString qualifiedName);
|
||||
NodeList getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
||||
NodeList getElementsByClassName(DOMString classNames);
|
||||
|
||||
readonly attribute HTMLCollection children;
|
||||
readonly attribute Element? firstElementChild;
|
||||
readonly attribute Element? lastElementChild;
|
||||
readonly attribute Element? previousElementSibling;
|
||||
readonly attribute Element? nextElementSibling;
|
||||
readonly attribute unsigned long childElementCount;
|
||||
|
||||
// NEW
|
||||
// Invalid WebIDL https://www.w3.org/Bugs/Public/show_bug.cgi?id=15346
|
||||
//void prepend((Node or DOMString)... nodes);
|
||||
//void append((Node or DOMString)... nodes);
|
||||
//void before((Node or DOMString)... nodes);
|
||||
//void after((Node or DOMString)... nodes);
|
||||
//void replace((Node or DOMString)... nodes);
|
||||
void remove();
|
||||
HTMLCollection getElementsByTagName(DOMString localName);
|
||||
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
||||
HTMLCollection getElementsByClassName(DOMString classNames);
|
||||
};
|
||||
|
||||
interface Attr {
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString localName;
|
||||
attribute DOMString value;
|
||||
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString? namespaceURI;
|
||||
readonly attribute DOMString? prefix;
|
||||
readonly attribute DOMString localName;
|
||||
};
|
||||
|
||||
interface CharacterData : Node {
|
||||
|
@ -336,15 +303,9 @@ interface CharacterData : Node {
|
|||
void insertData(unsigned long offset, DOMString data);
|
||||
void deleteData(unsigned long offset, unsigned long count);
|
||||
void replaceData(unsigned long offset, unsigned long count, DOMString data);
|
||||
|
||||
// NEW
|
||||
// Invalid WebIDL https://www.w3.org/Bugs/Public/show_bug.cgi?id=15346
|
||||
//void before((Node or DOMString)... nodes);
|
||||
//void after((Node or DOMString)... nodes);
|
||||
//void replace((Node or DOMString)... nodes);
|
||||
void remove();
|
||||
};
|
||||
|
||||
[Constructor(optional DOMString data)]
|
||||
interface Text : CharacterData {
|
||||
Text splitText(unsigned long offset);
|
||||
readonly attribute DOMString wholeText;
|
||||
|
@ -354,9 +315,11 @@ interface ProcessingInstruction : CharacterData {
|
|||
readonly attribute DOMString target;
|
||||
};
|
||||
|
||||
[Constructor(optional DOMString data)]
|
||||
interface Comment : CharacterData {
|
||||
};
|
||||
|
||||
[Constructor]
|
||||
interface Range {
|
||||
readonly attribute Node startContainer;
|
||||
readonly attribute unsigned long startOffset;
|
||||
|
@ -428,8 +391,7 @@ interface TreeWalker {
|
|||
|
||||
[Callback]
|
||||
interface NodeFilter {
|
||||
|
||||
// Constants for acceptNode
|
||||
// Constants for acceptNode()
|
||||
const unsigned short FILTER_ACCEPT = 1;
|
||||
const unsigned short FILTER_REJECT = 2;
|
||||
const unsigned short FILTER_SKIP = 3;
|
||||
|
@ -452,6 +414,7 @@ interface NodeFilter {
|
|||
unsigned short acceptNode(Node node);
|
||||
};
|
||||
|
||||
[ArrayClass]
|
||||
interface NodeList {
|
||||
getter Node? item(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
|
@ -463,20 +426,14 @@ interface HTMLCollection {
|
|||
getter object? namedItem(DOMString name); // only returns Element
|
||||
};
|
||||
|
||||
interface DOMStringList {
|
||||
readonly attribute unsigned long length;
|
||||
getter DOMString? item(unsigned long index);
|
||||
boolean contains(DOMString string);
|
||||
};
|
||||
|
||||
interface DOMTokenList {
|
||||
readonly attribute unsigned long length;
|
||||
getter DOMString? item(unsigned long index);
|
||||
boolean contains(DOMString token);
|
||||
void add(DOMString token);
|
||||
void remove(DOMString token);
|
||||
boolean toggle(DOMString token);
|
||||
stringifier DOMString ();
|
||||
void add(DOMString... tokens);
|
||||
void remove(DOMString... tokens);
|
||||
boolean toggle(DOMString token, optional boolean force);
|
||||
stringifier;
|
||||
};
|
||||
|
||||
interface DOMSettableTokenList : DOMTokenList {
|
||||
|
@ -509,8 +466,8 @@ idlArray.add_objects({
|
|||
ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
|
||||
Comment: ['document.createComment("abc")'],
|
||||
Range: ['document.createRange()', 'detachedRange'],
|
||||
NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null)'],
|
||||
TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null)'],
|
||||
NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
|
||||
TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
|
||||
NodeList: ['document.querySelectorAll("script")'],
|
||||
HTMLCollection: ['document.body.children'],
|
||||
DOMTokenList: ['document.body.classList'],
|
||||
|
|
|
@ -17,7 +17,6 @@ MOCHITEST_FILES := \
|
|||
test_CharacterData-insertData.html \
|
||||
test_CharacterData-remove.html \
|
||||
test_CharacterData-replaceData.html \
|
||||
test_ChildNode-remove.js \
|
||||
test_Document-adoptNode.html \
|
||||
test_Document-createComment.html \
|
||||
test_Document-createElement.html \
|
||||
|
@ -27,6 +26,7 @@ MOCHITEST_FILES := \
|
|||
test_Document-createProcessingInstruction-literal-1.xhtml \
|
||||
test_Document-createProcessingInstruction-literal-2.xhtml \
|
||||
test_Document-createProcessingInstruction.xhtml \
|
||||
test_Document-createTreeWalker.html \
|
||||
test_Document-getElementById.html \
|
||||
test_Document-getElementsByTagName.html \
|
||||
test_Document-getElementsByTagNameNS.html \
|
||||
|
@ -47,6 +47,7 @@ MOCHITEST_FILES := \
|
|||
test_Event-defaultPrevented.html \
|
||||
test_Event-initEvent.html \
|
||||
test_EventTarget-dispatchEvent.html \
|
||||
test_Event-type.html \
|
||||
test_historical.html \
|
||||
test_interfaces.html \
|
||||
test_Node-appendChild.html \
|
||||
|
@ -73,6 +74,7 @@ MOCHITEST_FILES := \
|
|||
case.js \
|
||||
creators.js \
|
||||
constants.js \
|
||||
ChildNode-remove.js \
|
||||
Document-createProcessingInstruction.js \
|
||||
productions.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -18,7 +18,9 @@ test(function() {
|
|||
* the doctype argument
|
||||
* the expected exception, or null if none
|
||||
*/
|
||||
[null, null, false, new TypeError()],
|
||||
[null, null, null, null],
|
||||
[null, undefined, null, null],
|
||||
[null, "", null, null],
|
||||
[null, "foo", null, null],
|
||||
[null, "1foo", null, "INVALID_CHARACTER_ERR"],
|
||||
|
@ -33,6 +35,22 @@ test(function() {
|
|||
[null, "xml:foo", null, "NAMESPACE_ERR"],
|
||||
[null, "xmlns:foo", null, "NAMESPACE_ERR"],
|
||||
[null, "xmlfoo:bar", null, "NAMESPACE_ERR"],
|
||||
[undefined, null, undefined, null],
|
||||
[undefined, undefined, undefined, null],
|
||||
[undefined, "", undefined, null],
|
||||
[undefined, "foo", undefined, null],
|
||||
[undefined, "1foo", undefined, "INVALID_CHARACTER_ERR"],
|
||||
[undefined, "f1oo", undefined, null],
|
||||
[undefined, "foo1", undefined, null],
|
||||
[undefined, ":foo", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "f:oo", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "foo:", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "xml", undefined, null],
|
||||
[undefined, "xmlns", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "xmlfoo", undefined, null],
|
||||
[undefined, "xml:foo", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "xmlns:foo", undefined, "NAMESPACE_ERR"],
|
||||
[undefined, "xmlfoo:bar", undefined, "NAMESPACE_ERR"],
|
||||
["http://example.com/", null, null, null],
|
||||
["http://example.com/", "", null, null],
|
||||
["http://example.com/", "foo", null, null],
|
||||
|
@ -108,36 +126,28 @@ test(function() {
|
|||
["foo:", "xml:foo", null, "NAMESPACE_ERR"],
|
||||
["foo:", "xmlns:foo", null, "NAMESPACE_ERR"],
|
||||
["foo:", "xmlfoo:bar", null, null],
|
||||
[null, null, document.implementation.createDocumentType("foo", "", ""), null],
|
||||
[null, null, document.doctype, null], // This causes a horrible WebKit bug (now fixed in trunk).
|
||||
[null, null, function() {
|
||||
var foo = document.implementation.createDocumentType("foo", "", "");
|
||||
document.implementation.createDocument(null, null, foo);
|
||||
return foo;
|
||||
}(), null], // DOCTYPE already associated with a document.
|
||||
[null, null, function() {
|
||||
var bar = document.implementation.createDocument(null, null, null);
|
||||
return bar.implementation.createDocumentType("bar", "", "");
|
||||
}(), null], // DOCTYPE created by a different implementation.
|
||||
[null, null, function() {
|
||||
var bar = document.implementation.createDocument(null, null, null);
|
||||
var magic = bar.implementation.createDocumentType("bar", "", "");
|
||||
bar.implementation.createDocument(null, null, magic);
|
||||
return magic;
|
||||
}(), null], // DOCTYPE created by a different implementation and already associated with a document.
|
||||
[null, "foo", document.implementation.createDocumentType("foo", "", ""), null],
|
||||
["foo", null, document.implementation.createDocumentType("foo", "", ""), null],
|
||||
["foo", "bar", document.implementation.createDocumentType("foo", "", ""), null],
|
||||
]
|
||||
|
||||
try { // XXX merge?!
|
||||
var tempTests = tests.concat([
|
||||
[null, null, document.implementation.createDocumentType("foo", "", ""), null],
|
||||
[null, null, document.doctype, "WRONG_DOCUMENT_ERR"], // This causes a horrible WebKit bug (now fixed in trunk).
|
||||
[null, null, function() {
|
||||
var foo = document.implementation.createDocumentType("foo", "", "");
|
||||
document.implementation.createDocument(null, null, foo);
|
||||
return foo;
|
||||
}(), "WRONG_DOCUMENT_ERR"], // DOCTYPE already associated with a document.
|
||||
[null, null, function() {
|
||||
var bar = document.implementation.createDocument(null, null, null);
|
||||
return bar.implementation.createDocumentType("bar", "", "");
|
||||
}(), null], // DOCTYPE created by a different implementation.
|
||||
[null, null, function() {
|
||||
var bar = document.implementation.createDocument(null, null, null);
|
||||
var magic = bar.implementation.createDocumentType("bar", "", "");
|
||||
bar.implementation.createDocument(null, null, magic);
|
||||
return magic;
|
||||
}(), "WRONG_DOCUMENT_ERR"], // DOCTYPE created by a different implementation and already associated with a document.
|
||||
[null, "foo", document.implementation.createDocumentType("foo", "", ""), null],
|
||||
["foo", null, document.implementation.createDocumentType("foo", "", ""), null],
|
||||
["foo", "bar", document.implementation.createDocumentType("foo", "", ""), null],
|
||||
]);
|
||||
tests = tempTests;
|
||||
} catch (e) {
|
||||
assert_unreached()
|
||||
}
|
||||
|
||||
tests.forEach(function(t, i) {
|
||||
test(function() {
|
||||
var namespace = t[0], qualifiedName = t[1], doctype = t[2], expected = t[3]
|
||||
|
@ -147,14 +157,31 @@ test(function() {
|
|||
var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
|
||||
assert_equals(doc.nodeType, Node.DOCUMENT_NODE)
|
||||
assert_equals(doc.nodeType, doc.DOCUMENT_NODE)
|
||||
if (qualifiedName === "" || qualifiedName === null) {
|
||||
var omitRootElement = qualifiedName === null || String(qualifiedName) === ""
|
||||
if (omitRootElement) {
|
||||
assert_equals(doc.documentElement, null)
|
||||
} else {
|
||||
assert_not_equals(doc.documentElement, null)
|
||||
assert_equals(doc.documentElement.nodeType, Node.ELEMENT_NODE)
|
||||
var element = doc.documentElement
|
||||
assert_not_equals(element, null)
|
||||
assert_equals(element.nodeType, Node.ELEMENT_NODE)
|
||||
assert_equals(element.ownerDocument, doc)
|
||||
var qualified = String(qualifiedName), names = []
|
||||
if (qualified.indexOf(":") >= 0) {
|
||||
names = qualified.split(":", 2)
|
||||
} else {
|
||||
names = [null, qualified]
|
||||
}
|
||||
assert_equals(element.prefix, names[0])
|
||||
assert_equals(element.localName, names[1])
|
||||
assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
|
||||
}
|
||||
assert_equals(doc.doctype, doctype)
|
||||
assert_equals(doc.childNodes.length, !!qualifiedName + !!doctype)
|
||||
if (!doctype) {
|
||||
assert_equals(doc.doctype, null)
|
||||
} else {
|
||||
assert_equals(doc.doctype, doctype)
|
||||
assert_equals(doc.doctype.ownerDocument, doc)
|
||||
}
|
||||
assert_equals(doc.childNodes.length, !omitRootElement + !!doctype)
|
||||
}
|
||||
}, "createDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
|
||||
})
|
||||
|
|
|
@ -10,6 +10,18 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
function toASCIIUppercase(str) {
|
||||
var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
|
||||
var res = "";
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
if ("a" <= str[i] && str[i] <= "z") {
|
||||
res += String.fromCharCode(str.charCodeAt(i) - diff);
|
||||
} else {
|
||||
res += str[i];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
test(function() {
|
||||
var HTMLNS = "http://www.w3.org/1999/xhtml",
|
||||
valid = [
|
||||
|
@ -32,7 +44,10 @@ test(function() {
|
|||
["xmlfoo:bar", "xmlfoo:bar"],
|
||||
["svg", "svg"],
|
||||
["math", "math"],
|
||||
["FOO", "foo"]
|
||||
["FOO", "foo"],
|
||||
["mar\u212a", "mar\u212a"],
|
||||
["\u0130nput", "\u0130nput"],
|
||||
["\u0131nput", "\u0131nput"]
|
||||
],
|
||||
invalid = [
|
||||
"",
|
||||
|
@ -56,7 +71,7 @@ test(function() {
|
|||
assert_true(elt instanceof Element)
|
||||
assert_true(elt instanceof Node)
|
||||
assert_equals(elt.localName, t[1])
|
||||
assert_equals(elt.tagName, t[1].toUpperCase())
|
||||
assert_equals(elt.tagName, toASCIIUppercase(t[1]))
|
||||
assert_equals(elt.prefix, null)
|
||||
assert_equals(elt.namespaceURI, HTMLNS)
|
||||
}, "createElement(" + format_value(t[0]) + ")");
|
||||
|
|
|
@ -22,7 +22,7 @@ function testAlias(arg, iface) {
|
|||
["HTMLEvents", "Event"],
|
||||
["MouseEvent", "MouseEvent"],
|
||||
["MouseEvents", "MouseEvent"],
|
||||
["UIEvent", "UIEvent"]
|
||||
["UIEvent", "UIEvent"],
|
||||
["UIEvents", "UIEvent"]
|
||||
].forEach(function(alias) {
|
||||
testAlias(alias[0], alias[1]);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Document.createTreeWalker</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
test(function() {
|
||||
assert_throws(new TypeError(), function() {
|
||||
document.createTreeWalker();
|
||||
});
|
||||
}, "Required arguments to createTreeWalker should be required.");
|
||||
test(function() {
|
||||
var tw = document.createTreeWalker(document.body);
|
||||
assert_equals(tw.root, document.body);
|
||||
assert_equals(tw.currentNode, document.body);
|
||||
assert_equals(tw.whatToShow, 0xFFFFFFFF);
|
||||
assert_equals(tw.filter, null);
|
||||
}, "Optional arguments to createTreeWalker should be optional (1 passed).");
|
||||
test(function() {
|
||||
var tw = document.createTreeWalker(document.body, 42);
|
||||
assert_equals(tw.root, document.body);
|
||||
assert_equals(tw.currentNode, document.body);
|
||||
assert_equals(tw.whatToShow, 42);
|
||||
assert_equals(tw.filter, null);
|
||||
}, "Optional arguments to createTreeWalker should be optional (2 passed).");
|
||||
test(function() {
|
||||
var tw = document.createTreeWalker(document.body, 42, null);
|
||||
assert_equals(tw.root, document.body);
|
||||
assert_equals(tw.currentNode, document.body);
|
||||
assert_equals(tw.whatToShow, 42);
|
||||
assert_equals(tw.filter, null);
|
||||
}, "Optional arguments to createTreeWalker should be optional (3 passed, null).");
|
||||
test(function() {
|
||||
var fn = function() {};
|
||||
var tw = document.createTreeWalker(document.body, 42, fn);
|
||||
assert_equals(tw.root, document.body);
|
||||
assert_equals(tw.currentNode, document.body);
|
||||
assert_equals(tw.whatToShow, 42);
|
||||
assert_equals(tw.filter, fn);
|
||||
}, "Optional arguments to createTreeWalker should be optional (3 passed, function).");
|
||||
</script>
|
|
@ -5,22 +5,71 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<pre id="x"></pre>
|
||||
<script>
|
||||
// TODO: getElementsByTagName("*")
|
||||
test(function() {
|
||||
assert_false(document.getElementsByTagName("html") instanceof NodeList, "NodeList")
|
||||
assert_true(document.getElementsByTagName("html") instanceof HTMLCollection, "HTMLCollection")
|
||||
assert_false(document.getElementsByTagName("html") instanceof NodeList,
|
||||
"Should not return a NodeList")
|
||||
assert_true(document.getElementsByTagName("html") instanceof HTMLCollection,
|
||||
"Should return an HTMLCollection")
|
||||
}, "Interfaces")
|
||||
test(function() {
|
||||
var firstCollection = document.getElementsByTagName("html"),
|
||||
secondCollection = document.getElementsByTagName("html")
|
||||
assert_true(firstCollection !== secondCollection || firstCollection === secondCollection,
|
||||
"Caching is allowed.")
|
||||
})
|
||||
assert_true(firstCollection !== secondCollection ||
|
||||
firstCollection === secondCollection)
|
||||
}, "Caching is allowed")
|
||||
|
||||
test(function() {
|
||||
var l = document.getElementsByTagName("nosuchtag")
|
||||
l[5] = "foopy"
|
||||
assert_equals(l[5], undefined)
|
||||
assert_equals(l.item(5), null)
|
||||
}, "Shouldn't be able to set unsigned properties on a HTMLCollection")
|
||||
}, "Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode)")
|
||||
test(function() {
|
||||
var l = document.getElementsByTagName("nosuchtag")
|
||||
assert_throws(new TypeError(), function() {
|
||||
"use strict";
|
||||
l[5] = "foopy"
|
||||
})
|
||||
assert_equals(l[5], undefined)
|
||||
assert_equals(l.item(5), null)
|
||||
}, "Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)")
|
||||
test(function() {
|
||||
var l = document.getElementsByTagName("nosuchtag")
|
||||
var fn = l.item;
|
||||
assert_equals(fn, HTMLCollection.prototype.item);
|
||||
l.item = "pass"
|
||||
assert_equals(l.item, "pass")
|
||||
assert_equals(HTMLCollection.prototype.item, fn);
|
||||
}, "Should be able to set expando shadowing a proto prop (item)")
|
||||
test(function() {
|
||||
var l = document.getElementsByTagName("nosuchtag")
|
||||
var fn = l.namedItem;
|
||||
assert_equals(fn, HTMLCollection.prototype.namedItem);
|
||||
l.namedItem = "pass"
|
||||
assert_equals(l.namedItem, "pass")
|
||||
assert_equals(HTMLCollection.prototype.namedItem, fn);
|
||||
}, "Should be able to set expando shadowing a proto prop (namedItem)")
|
||||
|
||||
test(function() {
|
||||
var list = document.getElementsByTagName('pre');
|
||||
var pre = list[0];
|
||||
assert_equals(pre.id, "x");
|
||||
assert_equals(list['x'], pre);
|
||||
|
||||
assert_true('x' in list, "'x' in list");
|
||||
assert_true(list.hasOwnProperty('x'), "list.hasOwnProperty('x')");
|
||||
|
||||
assert_array_equals(Object.getOwnPropertyNames(list).sort(), ["0", "x"]);
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(list, 'x');
|
||||
assert_equals(typeof desc, "object", "descriptor should be an object");
|
||||
assert_true(desc.enumerable, "desc.enumerable");
|
||||
assert_true(desc.configurable, "desc.configurable");
|
||||
}, "hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames")
|
||||
|
||||
test(function() {
|
||||
assert_equals(document.createElementNS("http://www.w3.org/1999/xhtml", "i").localName, "i") // Sanity
|
||||
var i = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I"))
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Event.type</title>
|
||||
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
|
||||
<link rel="help" href="http://dom.spec.whatwg.org/#dom-event-type">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var e = document.createEvent("Event")
|
||||
assert_equals(e.type, "");
|
||||
}, "Event.type should initially be the empty string");
|
||||
test(function() {
|
||||
var e = document.createEvent("Event")
|
||||
e.initEvent("foo", false, false)
|
||||
assert_equals(e.type, "foo")
|
||||
}, "Event.type should be initialized by initEvent");
|
||||
test(function() {
|
||||
var e = new Event("bar")
|
||||
assert_equals(e.type, "bar")
|
||||
}, "Event.type should be initialized by the constructor");
|
||||
</script>
|
|
@ -50,6 +50,7 @@ function iframeLoaded() {
|
|||
assert_true(doc1.doctype.isEqualNode(doc2.doctype), "doc1.doctype.isEqualNode(doc2.doctype)")
|
||||
assert_true(doc1.isEqualNode(doc2), "doc1.isEqualNode(doc2)")
|
||||
})
|
||||
internalSubset.done()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<script>
|
||||
var objects = [
|
||||
[NodeFilter, "NodeFilter interface object"],
|
||||
[NodeFilter.prototype, "NodeFilter prototype object"]
|
||||
]
|
||||
testConstants(objects, [
|
||||
["FILTER_ACCEPT", 1],
|
||||
|
|
|
@ -13,10 +13,10 @@ test(function() {
|
|||
assert_equals(r.endOffset, 0)
|
||||
assert_true(r.collapsed)
|
||||
r.detach()
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.startContainer })
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.startOffset })
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.endContainer })
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.endOffset })
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.collapsed })
|
||||
assert_equals(r.startContainer, document)
|
||||
assert_equals(r.endContainer, document)
|
||||
assert_equals(r.startOffset, 0)
|
||||
assert_equals(r.endOffset, 0)
|
||||
assert_true(r.collapsed)
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
test(function() {
|
||||
var range = document.createRange();
|
||||
range.detach();
|
||||
assert_throws("INVALID_STATE_ERR", function() {
|
||||
range.commonAncestorContainer();
|
||||
}, "Detached Range must throw INVALID_STATE_ERR on accessing commonAncestorContainer");
|
||||
assert_equals(range.commonAncestorContainer, document);
|
||||
}, "Detached Range")
|
||||
test(function() {
|
||||
var df = document.createDocumentFragment();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
test(function() {
|
||||
var r = document.createRange();
|
||||
r.detach()
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.comparePoint(document.body, 0) })
|
||||
assert_equals(r.comparePoint(document.body, 0), 1)
|
||||
})
|
||||
test(function() {
|
||||
var r = document.createRange();
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
test(function() {
|
||||
var r = document.createRange();
|
||||
r.detach()
|
||||
assert_throws("INVALID_STATE_ERR", function() { r.detach() })
|
||||
r.detach()
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -10,6 +10,7 @@ relativesrcdir := @relativesrcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES := \
|
||||
test_FormData-append.html \
|
||||
test_interfaces.html \
|
||||
test_setrequestheader-invalid-arguments.htm \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>FormData.append</title>
|
||||
<link rel=help href=http://xhr.spec.whatwg.org/#dom-formdata-append>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var fd = new FormData();
|
||||
fd.append("name", new String("value"));
|
||||
// TODO: test that it actually worked.
|
||||
}, "Passing a String object to FormData.append should work.");
|
||||
</script>
|
|
@ -2104,10 +2104,15 @@ TabChild::InitRenderingState()
|
|||
if (id != 0) {
|
||||
// Pushing layers transactions directly to a separate
|
||||
// compositor context.
|
||||
PCompositorChild* compositorChild = CompositorChild::Get();
|
||||
if (!compositorChild) {
|
||||
NS_WARNING("failed to get CompositorChild instance");
|
||||
return false;
|
||||
}
|
||||
shadowManager =
|
||||
CompositorChild::Get()->SendPLayersConstructor(be, id,
|
||||
&be,
|
||||
&maxTextureSize);
|
||||
compositorChild->SendPLayersConstructor(be, id,
|
||||
&be,
|
||||
&maxTextureSize);
|
||||
} else {
|
||||
// Pushing transactions to the parent content.
|
||||
shadowManager = remoteFrame->SendPLayersConstructor();
|
||||
|
|
|
@ -673,9 +673,10 @@ GonkGPSGeolocationProvider::Handle(const nsAString& aName,
|
|||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
NS_ENSURE_TRUE(cx, NS_OK);
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(aResult));
|
||||
|
||||
// When we get the APN, we attempt to call data_call_open of AGPS.
|
||||
if (aResult.isString()) {
|
||||
// NB: No need to enter a compartment to read the contents of a string.
|
||||
nsDependentJSString apn;
|
||||
apn.init(cx, aResult.toString());
|
||||
if (!apn.IsEmpty()) {
|
||||
|
|
|
@ -23,5 +23,5 @@ interface DOMImplementation {
|
|||
[TreatNullAs=EmptyString] DOMString qualifiedName,
|
||||
DocumentType? doctype);
|
||||
[Throws]
|
||||
Document createHTMLDocument(DOMString title);
|
||||
Document createHTMLDocument(optional DOMString title);
|
||||
};
|
||||
|
|
|
@ -339,6 +339,7 @@ test_webidl_files := \
|
|||
TestDictionary.webidl \
|
||||
TestExampleGen.webidl \
|
||||
TestJSImplGen.webidl \
|
||||
TestJSImplInheritanceGen.webidl \
|
||||
TestTypedef.webidl \
|
||||
$(NULL)
|
||||
else
|
||||
|
|
|
@ -172,9 +172,10 @@ public:
|
|||
|
||||
mXHR = new nsXMLHttpRequest();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(ownerWindow);
|
||||
if (NS_FAILED(mXHR->Init(mWorkerPrivate->GetPrincipal(),
|
||||
mWorkerPrivate->GetScriptContext(),
|
||||
ownerWindow, mWorkerPrivate->GetBaseURI()))) {
|
||||
global, mWorkerPrivate->GetBaseURI()))) {
|
||||
mXHR = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -385,6 +385,7 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker,
|
|||
ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
|
||||
mSize(0,0),
|
||||
mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
|
||||
mMultipartDecodedFrame(nullptr),
|
||||
mAnim(nullptr),
|
||||
mLoopCount(-1),
|
||||
mLockCount(0),
|
||||
|
@ -458,6 +459,8 @@ RasterImage::~RasterImage()
|
|||
for (unsigned int i = 0; i < mFrames.Length(); ++i)
|
||||
delete mFrames[i];
|
||||
|
||||
delete mMultipartDecodedFrame;
|
||||
|
||||
// Total statistics
|
||||
num_containers--;
|
||||
total_source_bytes -= mSourceData.Length();
|
||||
|
@ -1571,6 +1574,25 @@ RasterImage::DecodingComplete()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Double-buffer our frame in the multipart case, since we'll start decoding
|
||||
// into mFrames again immediately and this produces severe tearing.
|
||||
if (mMultipart) {
|
||||
if (mFrames.Length() == 1) {
|
||||
imgFrame* swapFrame = mMultipartDecodedFrame;
|
||||
mMultipartDecodedFrame = GetImgFrameNoDecode(GetCurrentFrameIndex());
|
||||
mFrames.Clear();
|
||||
if (swapFrame) {
|
||||
mFrames.AppendElement(swapFrame);
|
||||
}
|
||||
} else {
|
||||
// Don't double buffer for animated multipart images. It entails more
|
||||
// complexity and it's not really needed since we already are smart about
|
||||
// not displaying the still-decoding frame of an animated image. We may
|
||||
// have already stored an extra frame, though, so we'll release it here.
|
||||
delete mMultipartDecodedFrame;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2473,6 +2495,10 @@ RasterImage::Discard(bool force)
|
|||
mScaleResult.status = SCALE_INVALID;
|
||||
mScaleResult.frame = nullptr;
|
||||
|
||||
// Clear the last decoded multipart frame.
|
||||
delete mMultipartDecodedFrame;
|
||||
mMultipartDecodedFrame = nullptr;
|
||||
|
||||
// Flag that we no longer have decoded frames for this image
|
||||
mDecoded = false;
|
||||
|
||||
|
@ -2817,7 +2843,7 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
|
|||
// data, so signal that we want a full decode and give up for now.
|
||||
if (!mHasSize) {
|
||||
mWantFullDecode = true;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3193,9 +3219,19 @@ RasterImage::Draw(gfxContext *aContext,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
uint32_t frameIndex = aWhichFrame == FRAME_FIRST ? 0
|
||||
: GetCurrentImgFrameIndex();
|
||||
imgFrame *frame = GetDrawableImgFrame(frameIndex);
|
||||
imgFrame* frame = nullptr;
|
||||
|
||||
if (mMultipart) {
|
||||
// In the multipart case we prefer to use mMultipartDecodedFrame, which is
|
||||
// the most recent one we completely decoded, rather than display the real
|
||||
// current frame and risk severe tearing.
|
||||
frame = mMultipartDecodedFrame;
|
||||
}
|
||||
if (!frame) {
|
||||
uint32_t frameIndex = aWhichFrame == FRAME_FIRST ? 0
|
||||
: GetCurrentImgFrameIndex();
|
||||
frame = GetDrawableImgFrame(frameIndex);
|
||||
}
|
||||
if (!frame) {
|
||||
return NS_OK; // Getting the frame (above) touches the image and kicks off decoding
|
||||
}
|
||||
|
@ -3327,35 +3363,38 @@ bool
|
|||
RasterImage::IsDecodeFinished()
|
||||
{
|
||||
// Precondition
|
||||
mDecodingMutex.AssertCurrentThreadOwns();
|
||||
NS_ABORT_IF_FALSE(mDecoder, "Can't call IsDecodeFinished() without decoder!");
|
||||
MOZ_ASSERT(mDecodeRequest);
|
||||
|
||||
// Assume it's not finished
|
||||
bool decodeFinished = false;
|
||||
|
||||
// The decode is complete if we got what we wanted...
|
||||
// The decode is complete if we got what we wanted.
|
||||
if (mDecoder->IsSizeDecode()) {
|
||||
if (mHasSize)
|
||||
decodeFinished = true;
|
||||
if (mDecoder->HasSize()) {
|
||||
return true;
|
||||
}
|
||||
} else if (mDecoder->GetDecodeDone()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (mDecoded)
|
||||
decodeFinished = true;
|
||||
|
||||
// If the decoder returned because it needed a new frame and we haven't
|
||||
// written to it since then, the decoder may be storing data that it hasn't
|
||||
// decoded yet.
|
||||
if (mDecoder->NeedsNewFrame() || mDecodeRequest->mAllocatedNewFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... but if we're waiting for a new frame, we're not done.
|
||||
if (mDecoder && mDecoder->NeedsNewFrame())
|
||||
decodeFinished = false;
|
||||
|
||||
// Otherwise, if we have all the source data and wrote all the source data,
|
||||
// we're done.
|
||||
//
|
||||
// (NB - This can be distinct from the above case even for non-erroneous
|
||||
// images because the decoder might not call DecodingComplete() until we
|
||||
// call Close() in ShutdownDecoder())
|
||||
else if (mHasSourceData && (mBytesDecoded == mSourceData.Length()))
|
||||
decodeFinished = true;
|
||||
// (NB - This can be the case even for non-erroneous images because
|
||||
// Decoder::GetDecodeDone() might not return true until after we call
|
||||
// Decoder::Finish() in ShutdownDecoder())
|
||||
if (mHasSourceData && (mBytesDecoded == mSourceData.Length())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return decodeFinished;
|
||||
// If we get here, assume it's not finished.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Indempotent error flagging routine. If a decoder is open, shuts it down.
|
||||
|
@ -3471,8 +3510,7 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
|
|||
|
||||
// If the decode finished, or we're specifically being told to shut down,
|
||||
// tell the image and shut down the decoder.
|
||||
if (image->mDecoder->GetDecodeDone() || image->IsDecodeFinished() ||
|
||||
aIntent != eShutdownIntent_Done) {
|
||||
if (image->IsDecodeFinished() || aIntent != eShutdownIntent_Done) {
|
||||
done = true;
|
||||
|
||||
// Hold on to a reference to the decoder until we're done with it
|
||||
|
@ -3523,7 +3561,8 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
|
|||
}
|
||||
|
||||
// If we were a size decode and a full decode was requested, now's the time.
|
||||
if (NS_SUCCEEDED(rv) && done && wasSize && image->mWantFullDecode) {
|
||||
if (NS_SUCCEEDED(rv) && aIntent != eShutdownIntent_Error && done &&
|
||||
wasSize && image->mWantFullDecode) {
|
||||
image->mWantFullDecode = false;
|
||||
|
||||
// If we're not meant to be storing source data and we just got the size,
|
||||
|
@ -3683,7 +3722,7 @@ RasterImage::DecodePool::DecodeJob::Run()
|
|||
}
|
||||
|
||||
// If someone came along and synchronously decoded us, there's nothing for us to do.
|
||||
if (!mRequest->mAllocatedNewFrame && (!mImage->mDecoder || mImage->IsDecodeFinished())) {
|
||||
if (!mImage->mDecoder || mImage->IsDecodeFinished()) {
|
||||
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3906,11 +3945,6 @@ RasterImage::DecodeDoneWorker::Run()
|
|||
|
||||
mImage->FinishedSomeDecoding(eShutdownIntent_Done, mRequest);
|
||||
|
||||
// If we didn't finish decoding yet, try again
|
||||
if (mImage->mDecoder) {
|
||||
DecodePool::Singleton()->RequestDecode(mImage);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -729,7 +729,10 @@ private: // data
|
|||
// IMPORTANT: if you use mFrames in a method, call EnsureImageIsDecoded() first
|
||||
// to ensure that the frames actually exist (they may have been discarded to save
|
||||
// memory, or we may be decoding on draw).
|
||||
nsTArray<imgFrame *> mFrames;
|
||||
nsTArray<imgFrame*> mFrames;
|
||||
|
||||
// The last frame we decoded for multipart images.
|
||||
imgFrame* mMultipartDecodedFrame;
|
||||
|
||||
nsCOMPtr<nsIProperties> mProperties;
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "BackstagePass.h"
|
||||
|
||||
#include "TestShellChild.h"
|
||||
#include "TestShellParent.h"
|
||||
|
||||
|
@ -1035,15 +1037,16 @@ XPCShellEnvironment::Init()
|
|||
|
||||
AutoContextPusher pusher(this);
|
||||
|
||||
nsCOMPtr<nsIXPCScriptable> backstagePass;
|
||||
rv = rtsvc->GetBackstagePass(getter_AddRefs(backstagePass));
|
||||
nsRefPtr<BackstagePass> backstagePass;
|
||||
rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to get backstage pass from rtsvc!");
|
||||
NS_ERROR("Failed to create backstage pass!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx,
|
||||
static_cast<nsIGlobalObject *>(backstagePass),
|
||||
principal, 0,
|
||||
JS::SystemZone,
|
||||
getter_AddRefs(holder));
|
||||
|
@ -1059,6 +1062,7 @@ XPCShellEnvironment::Init()
|
|||
return false;
|
||||
}
|
||||
|
||||
backstagePass->SetGlobalObject(globalObj);
|
||||
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
|
|
@ -37,10 +37,23 @@ void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc)
|
|||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
/* xpconnect related utility functions implemented in jsd_xpc.cpp */
|
||||
|
||||
extern void
|
||||
global_finalize(JSFreeOp* fop, JSObject* obj);
|
||||
|
||||
extern JSObject*
|
||||
CreateJSDGlobal(JSContext *cx, JSClass *clasp);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
static JSClass global_class = {
|
||||
"JSDGlobal", JSCLASS_GLOBAL_FLAGS,
|
||||
"JSDGlobal", JSCLASS_GLOBAL_FLAGS |
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, global_finalize
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
@ -108,7 +121,7 @@ _newJSDContext(JSRuntime* jsrt,
|
|||
JS_BeginRequest(jsdc->dumbContext);
|
||||
JS_SetOptions(jsdc->dumbContext, JS_GetOptions(jsdc->dumbContext));
|
||||
|
||||
jsdc->glob = JS_NewGlobalObject(jsdc->dumbContext, &global_class, NULL);
|
||||
jsdc->glob = CreateJSDGlobal(jsdc->dumbContext, &global_class);
|
||||
|
||||
if( ! jsdc->glob )
|
||||
goto label_newJSDContext_failure;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
/* XXX DOM dependency */
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "SandboxPrivate.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
|
||||
/*
|
||||
* defining CAUTIOUS_SCRIPTHOOK makes jsds disable GC while calling out to the
|
||||
|
@ -3434,6 +3436,36 @@ static const mozilla::Module kJSDModule = {
|
|||
|
||||
NSMODULE_DEFN(JavaScript_Debugger) = &kJSDModule;
|
||||
|
||||
void
|
||||
global_finalize(JSFreeOp *aFop, JSObject *aObj)
|
||||
{
|
||||
nsIScriptObjectPrincipal *sop =
|
||||
static_cast<nsIScriptObjectPrincipal *>(js::GetObjectPrivate(aObj));
|
||||
MOZ_ASSERT(sop);
|
||||
static_cast<SandboxPrivate *>(sop)->ForgetGlobalObject();
|
||||
NS_IF_RELEASE(sop);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
CreateJSDGlobal(JSContext *aCx, JSClass *aClasp)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrincipal> nullPrin = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
JSPrincipals *jsPrin = nsJSPrincipals::get(nullPrin);
|
||||
JSObject *global = JS_NewGlobalObject(aCx, aClasp, jsPrin);
|
||||
NS_ENSURE_TRUE(global, nullptr);
|
||||
|
||||
// We have created a new global let's attach a private to it
|
||||
// that implements nsIGlobalObject.
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sbp =
|
||||
new SandboxPrivate(nullPrin, global);
|
||||
JS_SetPrivate(global, sbp.forget().get());
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
* graveyard
|
||||
|
|
|
@ -610,7 +610,7 @@ template <class T>
|
|||
class HashTableEntry
|
||||
{
|
||||
template <class, class, class> friend class HashTable;
|
||||
typedef typename tl::StripConst<T>::result NonConstT;
|
||||
typedef typename mozilla::RemoveConst<T>::Type NonConstT;
|
||||
|
||||
HashNumber keyHash;
|
||||
mozilla::AlignedStorage2<NonConstT> mem;
|
||||
|
@ -677,7 +677,7 @@ class HashTableEntry
|
|||
template <class T, class HashPolicy, class AllocPolicy>
|
||||
class HashTable : private AllocPolicy
|
||||
{
|
||||
typedef typename tl::StripConst<T>::result NonConstT;
|
||||
typedef typename mozilla::RemoveConst<T>::Type NonConstT;
|
||||
typedef typename HashPolicy::KeyType Key;
|
||||
typedef typename HashPolicy::Lookup Lookup;
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче