This commit is contained in:
Ms2ger 2013-04-04 14:15:56 +02:00
Родитель 4d9b24f0cb 870eab27c7
Коммит 97ae827742
162 изменённых файлов: 4014 добавлений и 1707 удалений

Просмотреть файл

@ -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 interfaces 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 nodes childNodes are included.
boolean attributes; // If true, mutations affecting elements 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;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше