Compare commits
211
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a4dc8de41 | ||
|
|
18595b01b6 | ||
|
|
f7215fc685 | ||
|
|
08521d4651 | ||
|
|
00b177d75f | ||
|
|
a89a071049 | ||
|
|
f9dc8a091a | ||
|
|
944299ed6c | ||
|
|
0e1441155c | ||
|
|
7bf5dfe4e4 | ||
|
|
d4c34fc9f7 | ||
|
|
6811005551 | ||
|
|
464cefa127 | ||
|
|
c94a1ab5d3 | ||
|
|
8aa5b35605 | ||
|
|
25dd1fb31a | ||
|
|
d8cf2c8b44 | ||
|
|
938c5d08d4 | ||
|
|
7fca2b8de3 | ||
|
|
ef19ad3ffd | ||
|
|
ab88527fe6 | ||
|
|
6c0ff1881a | ||
|
|
1e7f4c8474 | ||
|
|
fdf491d4ec | ||
|
|
1f4cceca43 | ||
|
|
542eaca577 | ||
|
|
1cb6f56418 | ||
|
|
a503e883d9 | ||
|
|
347681c219 | ||
|
|
2984237f4f | ||
|
|
1c4a73de71 | ||
|
|
d27df4d88f | ||
|
|
9562888e77 | ||
|
|
5536b38401 | ||
|
|
c011b271a1 | ||
|
|
c21fb81d3e | ||
|
|
5a3dcf5939 | ||
|
|
1d709fe942 | ||
|
|
e55c16146f | ||
|
|
997a9a3e13 | ||
|
|
008f38579c | ||
|
|
d943e86b28 | ||
|
|
3f2d707a83 | ||
|
|
b145a93ad6 | ||
|
|
3056028db4 | ||
|
|
b4dac14720 | ||
|
|
76694b956f | ||
|
|
9fab5b3e3c | ||
|
|
d54491fdd0 | ||
|
|
00c3c3a546 | ||
|
|
1da5c344be | ||
|
|
76d66b5dad | ||
|
|
e502735eb2 | ||
|
|
edfebe1b99 | ||
|
|
250e4f75da | ||
|
|
53f1bdd9c2 | ||
|
|
ade298d0a7 | ||
|
|
387b01ce14 | ||
|
|
47d2094329 | ||
|
|
43f9a8e1f0 | ||
|
|
30e287371f | ||
|
|
a9246d7b28 | ||
|
|
db1d73f05d | ||
|
|
72b14ea177 | ||
|
|
430c4a3f79 | ||
|
|
93ed92f63b | ||
|
|
4a1312c060 | ||
|
|
303e1ecf34 | ||
|
|
57b0e4a65b | ||
|
|
804a301068 | ||
|
|
aedb8a4d08 | ||
|
|
93072ab51e | ||
|
|
ca11a325bd | ||
|
|
3b088af0b1 | ||
|
|
09e52646e9 | ||
|
|
26ca6f4fcc | ||
|
|
b467d710ac | ||
|
|
f4f11fada8 | ||
|
|
43b3b47426 | ||
|
|
77f8cae06e | ||
|
|
daa31cfd59 | ||
|
|
b4ad4b7293 | ||
|
|
a2947909e8 | ||
|
|
bc2d0521e7 | ||
|
|
95ca42dd06 | ||
|
|
0c0dfca015 | ||
|
|
17cd2e4d07 | ||
|
|
f305547835 | ||
|
|
5ee86104a8 | ||
|
|
0ab247bee9 | ||
|
|
5370edc560 | ||
|
|
f27b6cbd21 | ||
|
|
de3485ed67 | ||
|
|
7f8489bc11 | ||
|
|
8c1cf4cc02 | ||
|
|
b8fbac6365 | ||
|
|
c7cc4ef650 | ||
|
|
9d1789b62f | ||
|
|
9a1c99e1a2 | ||
|
|
abc435f18e | ||
|
|
2e6dab8672 | ||
|
|
e0b95b12da | ||
|
|
722ecd0d97 | ||
|
|
e72cc38641 | ||
|
|
ae227b8743 | ||
|
|
a268e57967 | ||
|
|
9f05dad78c | ||
|
|
ba0112d574 | ||
|
|
5b449bc031 | ||
|
|
b823c130c1 | ||
|
|
437d9da605 | ||
|
|
f49a57006f | ||
|
|
18096194f5 | ||
|
|
8ca0f22841 | ||
|
|
b4e9888d91 | ||
|
|
30b01396b4 | ||
|
|
9343129fbb | ||
|
|
e79ddda9de | ||
|
|
f84c92881d | ||
|
|
aeafa7fef8 | ||
|
|
ff3db332fe | ||
|
|
68d53612af | ||
|
|
0fb9b4abbf | ||
|
|
ab442f72b9 | ||
|
|
b85d16b615 | ||
|
|
cc7d9550bc | ||
|
|
bc2d2edbef | ||
|
|
bc5c6c7563 | ||
|
|
0d971f0c5a | ||
|
|
99d225ae7f | ||
|
|
4bb7951324 | ||
|
|
20c29f74b4 | ||
|
|
d9a4414ef0 | ||
|
|
56be1ceaef | ||
|
|
fd0ddefa03 | ||
|
|
00e3d12e1d | ||
|
|
3a81d02c0f | ||
|
|
5fbb929250 | ||
|
|
4cb28647fe | ||
|
|
002240592a | ||
|
|
8f95d938d5 | ||
|
|
c66294c51a | ||
|
|
abc96cf444 | ||
|
|
a3019dddc1 | ||
|
|
bd03f965a3 | ||
|
|
358d39d4bf | ||
|
|
77571794a3 | ||
|
|
a935ef810c | ||
|
|
eb731d1377 | ||
|
|
c275325fbf | ||
|
|
84da3d4817 | ||
|
|
c868ea1f58 | ||
|
|
d5e385dc73 | ||
|
|
d49758ace1 | ||
|
|
f3ee6e294f | ||
|
|
dea96fe9d3 | ||
|
|
29a5e8df12 | ||
|
|
51941fd085 | ||
|
|
64ea5dd93a | ||
|
|
a42d420ee5 | ||
|
|
060995dfff | ||
|
|
991bd7b460 | ||
|
|
db503078d0 | ||
|
|
8ee58d2591 | ||
|
|
c340a1dcd2 | ||
|
|
774a6aa4dd | ||
|
|
b2566429fc | ||
|
|
f66bcb4f23 | ||
|
|
0e7430735e | ||
|
|
905c7e8785 | ||
|
|
9d91a43142 | ||
|
|
53bac56f36 | ||
|
|
e85fff2f10 | ||
|
|
839236c912 | ||
|
|
1e3fddbe14 | ||
|
|
b5576d1485 | ||
|
|
524b466197 | ||
|
|
7d1b245754 | ||
|
|
64a0846a1c | ||
|
|
118bd414d4 | ||
|
|
3f319c5f29 | ||
|
|
8b06eaa8fc | ||
|
|
e62bd7c533 | ||
|
|
0839a82f80 | ||
|
|
4cbaf927d9 | ||
|
|
b4f364c385 | ||
|
|
6ede629146 | ||
|
|
c684599599 | ||
|
|
c9bfd79ae0 | ||
|
|
6d3f71d200 | ||
|
|
620e391be7 | ||
|
|
532a1355ce | ||
|
|
03367d9c41 | ||
|
|
6ebd205c8e | ||
|
|
7276ea00a7 | ||
|
|
7a5c56bc58 | ||
|
|
9e064c7045 | ||
|
|
6933bfe783 | ||
|
|
5e81fb065a | ||
|
|
f08b4276ea | ||
|
|
45d7dda330 | ||
|
|
a8f1878ff3 | ||
|
|
d0ec80aa86 | ||
|
|
a9257dea7d | ||
|
|
af5d12a154 | ||
|
|
fb4ebd7838 | ||
|
|
7ace23060a | ||
|
|
19504eed91 | ||
|
|
7c72b41e2c | ||
|
|
6fc971d8c0 | ||
|
|
a410f9e553 |
No files matched your search
@@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for ICU 78.1
|
||||
Clobber for libvpx changes
|
||||
@@ -112,5 +112,5 @@ function shutdownPromise(contentBrowser) {
|
||||
*/
|
||||
function forceGC() {
|
||||
Cu.forceCC();
|
||||
Cu.forceShrinkingGC();
|
||||
Cu.forceGC();
|
||||
}
|
||||
@@ -127,7 +127,6 @@ def old_configure_options(*options):
|
||||
'--enable-alsa',
|
||||
'--enable-appcompat-guid',
|
||||
'--enable-av1',
|
||||
'--enable-jxl',
|
||||
'--enable-b2g-bt',
|
||||
'--enable-b2g-camera',
|
||||
'--enable-b2g-ril',
|
||||
|
||||
@@ -33,12 +33,7 @@ EXPORTS.mozilla = [
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
# Compile this separately since nsExceptionHandler.h conflicts
|
||||
# with something from nsNullPrincipal.cpp.
|
||||
'BasePrincipal.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DomainPolicy.cpp',
|
||||
'nsJSPrincipals.cpp',
|
||||
'nsNullPrincipal.cpp',
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ EXPORTS.mozilla.chrome += [
|
||||
'RegistryMessageUtils.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
SOURCES += [
|
||||
'nsChromeProtocolHandler.cpp',
|
||||
'nsChromeRegistry.cpp',
|
||||
'nsChromeRegistryChrome.cpp',
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
# Referenced by milestone.py.
|
||||
#--------------------------------------------------------
|
||||
|
||||
6.8.0
|
||||
6.8.1
|
||||
@@ -348,11 +348,7 @@ ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
EXTRA_DSO_LDOPTS += -bundle
|
||||
else
|
||||
ifdef MOZ_IOS
|
||||
_LOADER_PATH := @rpath
|
||||
else
|
||||
_LOADER_PATH := @executable_path
|
||||
endif
|
||||
EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -130,6 +130,7 @@ marker.gcreason.label.DOM_WORKER=Periodic Worker GC
|
||||
marker.gcreason.label.INTER_SLICE_GC=Periodic Incremental GC Slice
|
||||
marker.gcreason.label.FULL_GC_TIMER=Periodic Full GC
|
||||
marker.gcreason.label.SHUTDOWN_CC=Shutdown
|
||||
marker.gcreason.label.FINISH_LARGE_EVALUATE=Large Eval
|
||||
marker.gcreason.label.DOM_WINDOW_UTILS=User Inactive
|
||||
marker.gcreason.label.USER_INACTIVE=User Inactive
|
||||
|
||||
@@ -168,5 +169,6 @@ marker.gcreason.description.DOM_WORKER=The worker was idle for a relatively long
|
||||
marker.gcreason.description.INTER_SLICE_GC=There has been a relatively long time since the last incremental GC slice.
|
||||
marker.gcreason.description.FULL_GC_TIMER=JavaScript returned to the event loop, and it has been a relatively long time since we performed a garbage collection.
|
||||
marker.gcreason.description.SHUTDOWN_CC=The browser destroyed a JavaScript runtime or context, and this was the final garbage collection before shutting down.
|
||||
marker.gcreason.description.FINISH_LARGE_EVALUATE=The browser finished evaluating a large script, and performed a GC because the script will never be run again.
|
||||
marker.gcreason.description.DOM_WINDOW_UTILS=The user was inactive for a long time. Took the opportunity to perform GC when it was unlikely to be noticed.
|
||||
marker.gcreason.description.USER_INACTIVE=The user was inactive for a long time. The browser took the opportunity to perform GC when it was unlikely to be noticed.
|
||||
@@ -1113,9 +1113,9 @@ Animation::ResumeAt(const TimeDuration& aReadyTime)
|
||||
// but it's currently not necessary.
|
||||
MOZ_ASSERT(mPendingState == PendingState::PlayPending,
|
||||
"Expected to resume a play-pending animation");
|
||||
MOZ_ASSERT(!mHoldTime.IsNull() || !mStartTime.IsNull(),
|
||||
MOZ_ASSERT(mHoldTime.IsNull() != mStartTime.IsNull(),
|
||||
"An animation in the play-pending state should have either a"
|
||||
" resolved hold time or resolved start time");
|
||||
" resolved hold time or resolved start time (but not both)");
|
||||
|
||||
// If we aborted a pending pause operation we will already have a start time
|
||||
// we should use. In all other cases, we resolve it from the ready time.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@@ -36,12 +35,16 @@ NS_INTERFACE_MAP_END
|
||||
void
|
||||
AnimationTimeline::NotifyAnimationUpdated(Animation& aAnimation)
|
||||
{
|
||||
if (mAnimations.EnsureInserted(&aAnimation)) {
|
||||
if (aAnimation.GetTimeline() && aAnimation.GetTimeline() != this) {
|
||||
aAnimation.GetTimeline()->RemoveAnimation(&aAnimation);
|
||||
}
|
||||
mAnimationOrder.insertBack(&aAnimation);
|
||||
if (mAnimations.Contains(&aAnimation)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAnimation.GetTimeline() && aAnimation.GetTimeline() != this) {
|
||||
aAnimation.GetTimeline()->RemoveAnimation(&aAnimation);
|
||||
}
|
||||
|
||||
mAnimations.PutEntry(&aAnimation);
|
||||
mAnimationOrder.insertBack(&aAnimation);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -185,7 +185,9 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
|
||||
PseudoElementHashEntry::KeyType key = { aElement, aPseudoType };
|
||||
|
||||
if (aRestyleType == RestyleType::Throttled) {
|
||||
elementsToRestyle.LookupForAdd(key).OrInsert([]() { return false; });
|
||||
if (!elementsToRestyle.Contains(key)) {
|
||||
elementsToRestyle.Put(key, false);
|
||||
}
|
||||
mPresContext->Document()->SetNeedStyleFlush();
|
||||
} else {
|
||||
// Get() returns 0 if the element is not found. It will also return
|
||||
|
||||
@@ -150,20 +150,22 @@ EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType)
|
||||
void
|
||||
EffectSet::AddEffect(dom::KeyframeEffectReadOnly& aEffect)
|
||||
{
|
||||
if (!mEffects.EnsureInserted(&aEffect)) {
|
||||
if (mEffects.Contains(&aEffect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mEffects.PutEntry(&aEffect);
|
||||
MarkCascadeNeedsUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
EffectSet::RemoveEffect(dom::KeyframeEffectReadOnly& aEffect)
|
||||
{
|
||||
if (!mEffects.EnsureRemoved(&aEffect)) {
|
||||
if (!mEffects.Contains(&aEffect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mEffects.RemoveEntry(&aEffect);
|
||||
MarkCascadeNeedsUpdate();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const
|
||||
|
||||
void
|
||||
Attr::GetTextContentInternal(nsAString& aTextContent,
|
||||
OOMReporter& aError)
|
||||
ErrorResult& aError)
|
||||
{
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public:
|
||||
// nsIDOMNode interface
|
||||
NS_FORWARD_NSIDOMNODE_TO_NSINODE
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
OOMReporter& aError) override;
|
||||
ErrorResult& aError) override;
|
||||
virtual void SetTextContentInternal(const nsAString& aTextContent,
|
||||
ErrorResult& aError) override;
|
||||
virtual void GetNodeValueInternal(nsAString& aNodeValue) override;
|
||||
|
||||
@@ -592,10 +592,7 @@ CustomElementRegistry::Define(const nsAString& aName,
|
||||
}
|
||||
|
||||
JSContext *cx = jsapi.cx();
|
||||
// Note: No calls that might run JS or trigger CC before this point, or
|
||||
// there's a (vanishingly small) chance of our constructor being nulled
|
||||
// before we access it.
|
||||
JS::Rooted<JSObject*> constructor(cx, aFunctionConstructor.CallableOrNull());
|
||||
JS::Rooted<JSObject*> constructor(cx, aFunctionConstructor.Callable());
|
||||
|
||||
/**
|
||||
* 1. If IsConstructor(constructor) is false, then throw a TypeError and abort
|
||||
@@ -928,7 +925,7 @@ CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
|
||||
return;
|
||||
}
|
||||
|
||||
aRetVal.setObject(*data->mConstructor->Callback(aCx));
|
||||
aRetVal.setObjectOrNull(data->mConstructor->Callable());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -953,11 +950,10 @@ CustomElementRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
auto entry = mWhenDefinedPromiseMap.LookupForAdd(nameAtom);
|
||||
if (entry) {
|
||||
promise = entry.Data();
|
||||
if (mWhenDefinedPromiseMap.Contains(nameAtom)) {
|
||||
mWhenDefinedPromiseMap.Get(nameAtom, getter_AddRefs(promise));
|
||||
} else {
|
||||
entry.OrInsert([&promise](){ return promise; });
|
||||
mWhenDefinedPromiseMap.Put(nameAtom, promise);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
|
||||
+28
-28
@@ -307,15 +307,9 @@ void
|
||||
Element::Focus(mozilla::ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
// Also other browsers seem to have the hack to not re-focus (and flush) when
|
||||
// the element is already focused.
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && domElement) {
|
||||
if (fm->CanSkipFocus(this)) {
|
||||
fm->NeedsFlushBeforeEventHandling(this);
|
||||
} else {
|
||||
aError = fm->SetFocus(domElement, 0);
|
||||
}
|
||||
aError = fm->SetFocus(domElement, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1581,9 +1575,6 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
|
||||
SetFlags(NODE_CHROME_ONLY_ACCESS);
|
||||
}
|
||||
if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) {
|
||||
aParent->SetMayHaveAnonymousChildren();
|
||||
}
|
||||
if (aParent->IsInShadowTree()) {
|
||||
ClearSubtreeRootPointer();
|
||||
SetFlags(NODE_IS_IN_SHADOW_TREE);
|
||||
@@ -4107,33 +4098,42 @@ enum nsPreviousIntersectionThreshold {
|
||||
void
|
||||
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
|
||||
{
|
||||
RegisteredIntersectionObservers()->LookupForAdd(aObserver).OrInsert([]() {
|
||||
// Value can be:
|
||||
// -2: Makes sure next calculated threshold always differs, leading to a
|
||||
// notification task being scheduled.
|
||||
// -1: Non-intersecting.
|
||||
// >= 0: Intersecting, valid index of aObserver->mThresholds.
|
||||
return eUninitialized;
|
||||
});
|
||||
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
if (observers->Contains(aObserver)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Value can be:
|
||||
// -2: Makes sure next calculated threshold always differs, leading to a
|
||||
// notification task being scheduled.
|
||||
// -1: Non-intersecting.
|
||||
// >= 0: Intersecting, valid index of aObserver->mThresholds.
|
||||
RegisteredIntersectionObservers()->Put(aObserver, eUninitialized);
|
||||
}
|
||||
|
||||
void
|
||||
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
|
||||
{
|
||||
RegisteredIntersectionObservers()->Remove(aObserver);
|
||||
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
observers->Remove(aObserver);
|
||||
}
|
||||
|
||||
bool
|
||||
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
|
||||
{
|
||||
bool updated = false;
|
||||
RegisteredIntersectionObservers()->LookupRemoveIf(aObserver,
|
||||
[&updated, aThreshold] (int32_t& aValue) {
|
||||
updated = aValue != aThreshold;
|
||||
aValue = aThreshold;
|
||||
return false; // don't remove the entry
|
||||
});
|
||||
return updated;
|
||||
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
if (!observers->Contains(aObserver)) {
|
||||
return false;
|
||||
}
|
||||
int32_t previousThreshold = observers->Get(aObserver);
|
||||
if (previousThreshold != aThreshold) {
|
||||
observers->Put(aObserver, aThreshold);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1295,10 +1295,10 @@ FragmentOrElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
|
||||
|
||||
void
|
||||
FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
|
||||
OOMReporter& aError)
|
||||
ErrorResult& aError)
|
||||
{
|
||||
if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
|
||||
aError.ReportOOM();
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError) override;
|
||||
mozilla::ErrorResult& aError) override;
|
||||
virtual void SetTextContentInternal(const nsAString& aTextContent,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
|
||||
|
||||
@@ -275,12 +275,9 @@ const NativePropertyHooks sWindowNamedPropertiesNativePropertyHooks[] = { {
|
||||
nullptr
|
||||
} };
|
||||
|
||||
// Note that this class doesn't need any reserved slots, but SpiderMonkey
|
||||
// asserts all proxy classes have at least one reserved slot.
|
||||
static const DOMIfaceAndProtoJSClass WindowNamedPropertiesClass = {
|
||||
PROXY_CLASS_DEF("WindowProperties",
|
||||
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1)),
|
||||
JSCLASS_IS_DOMIFACEANDPROTOJSCLASS),
|
||||
eNamedPropertiesObject,
|
||||
false,
|
||||
prototypes::id::_ID_Count,
|
||||
|
||||
@@ -1176,9 +1176,7 @@ nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode)
|
||||
void
|
||||
nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength)
|
||||
{
|
||||
if (!mRootNode) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mRootNode, "Must have root");
|
||||
|
||||
// Start searching at the root.
|
||||
nsINode* cur = mRootNode;
|
||||
|
||||
@@ -117,11 +117,14 @@ void
|
||||
nsDOMAttributeMap::DropAttribute(int32_t aNamespaceID, nsIAtom* aLocalName)
|
||||
{
|
||||
nsAttrKey attr(aNamespaceID, aLocalName);
|
||||
mAttributeCache.LookupRemoveIf(attr,
|
||||
[] (Attr* aNode) {
|
||||
aNode->SetMap(nullptr); // break link to map
|
||||
return true; // remove from cache
|
||||
});
|
||||
Attr *node = mAttributeCache.GetWeak(attr);
|
||||
if (node) {
|
||||
// Break link to map
|
||||
node->SetMap(nullptr);
|
||||
|
||||
// Remove from cache
|
||||
mAttributeCache.Remove(attr);
|
||||
}
|
||||
}
|
||||
|
||||
Attr*
|
||||
@@ -131,13 +134,13 @@ nsDOMAttributeMap::GetAttribute(mozilla::dom::NodeInfo* aNodeInfo)
|
||||
|
||||
nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
|
||||
|
||||
RefPtr<Attr>& entryValue = mAttributeCache.GetOrInsert(attr);
|
||||
Attr* node = entryValue;
|
||||
Attr* node = mAttributeCache.GetWeak(attr);
|
||||
if (!node) {
|
||||
// Newly inserted entry!
|
||||
RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
|
||||
entryValue = new Attr(this, ni.forget(), EmptyString());
|
||||
node = entryValue;
|
||||
RefPtr<Attr> newAttr =
|
||||
new Attr(this, ni.forget(), EmptyString());
|
||||
mAttributeCache.Put(attr, newAttr);
|
||||
node = newAttr;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
+20
-26
@@ -118,7 +118,8 @@ using namespace mozilla::dom;
|
||||
|
||||
#define NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, \
|
||||
_chromeOnly, _allowXBL) \
|
||||
{ nullptr, \
|
||||
{ #_class, \
|
||||
nullptr, \
|
||||
XPC_MAKE_CLASS_OPS(_flags), \
|
||||
XPC_MAKE_CLASS(#_class, _flags, \
|
||||
&sClassInfoData[eDOMClassInfo_##_class##_id].mClassOps), \
|
||||
@@ -159,18 +160,18 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
|
||||
DOM_BASE_SCRIPTABLE_FLAGS |
|
||||
XPC_SCRIPTABLE_WANT_PRECREATE |
|
||||
XPC_SCRIPTABLE_WANT_RESOLVE |
|
||||
XPC_SCRIPTABLE_WANT_HASINSTANCE |
|
||||
XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE)
|
||||
nsIXPCScriptable::WANT_PRECREATE |
|
||||
nsIXPCScriptable::WANT_RESOLVE |
|
||||
nsIXPCScriptable::WANT_HASINSTANCE |
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
|
||||
NS_DEFINE_CLASSINFO_DATA(DOMConstructor, nsDOMConstructorSH,
|
||||
DOM_BASE_SCRIPTABLE_FLAGS |
|
||||
XPC_SCRIPTABLE_WANT_PRECREATE |
|
||||
XPC_SCRIPTABLE_WANT_RESOLVE |
|
||||
XPC_SCRIPTABLE_WANT_HASINSTANCE |
|
||||
XPC_SCRIPTABLE_WANT_CALL |
|
||||
XPC_SCRIPTABLE_WANT_CONSTRUCT |
|
||||
XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE)
|
||||
nsIXPCScriptable::WANT_PRECREATE |
|
||||
nsIXPCScriptable::WANT_RESOLVE |
|
||||
nsIXPCScriptable::WANT_HASINSTANCE |
|
||||
nsIXPCScriptable::WANT_CALL |
|
||||
nsIXPCScriptable::WANT_CONSTRUCT |
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
|
||||
|
||||
// Misc Core related classes
|
||||
|
||||
@@ -193,13 +194,13 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager,
|
||||
nsMessageManagerSH<nsEventTargetSH>,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS |
|
||||
XPC_SCRIPTABLE_WANT_ENUMERATE |
|
||||
XPC_SCRIPTABLE_IS_GLOBAL_OBJECT)
|
||||
nsIXPCScriptable::WANT_ENUMERATE |
|
||||
nsIXPCScriptable::IS_GLOBAL_OBJECT)
|
||||
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentProcessMessageManager,
|
||||
nsMessageManagerSH<nsDOMGenericSH>,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS |
|
||||
XPC_SCRIPTABLE_WANT_ENUMERATE |
|
||||
XPC_SCRIPTABLE_IS_GLOBAL_OBJECT)
|
||||
nsIXPCScriptable::WANT_ENUMERATE |
|
||||
nsIXPCScriptable::IS_GLOBAL_OBJECT)
|
||||
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
|
||||
@@ -568,7 +569,7 @@ nsDOMClassInfo::Init()
|
||||
}
|
||||
|
||||
nsDOMClassInfoData& data = sClassInfoData[i];
|
||||
nameSpaceManager->RegisterClassName(data.mClass.name, i, data.mChromeOnly,
|
||||
nameSpaceManager->RegisterClassName(data.mName, i, data.mChromeOnly,
|
||||
data.mAllowXBL, &data.mNameUTF16);
|
||||
}
|
||||
|
||||
@@ -666,7 +667,7 @@ nsDOMClassInfo::GetFlags(uint32_t *aFlags)
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::GetClassName(char **aClassName)
|
||||
{
|
||||
*aClassName = NS_strdup(mData->mClass.name);
|
||||
*aClassName = NS_strdup(mData->mName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -685,13 +686,6 @@ nsDOMClassInfo::GetClass()
|
||||
return &mData->mClass;
|
||||
}
|
||||
|
||||
// virtual
|
||||
const JSClass*
|
||||
nsDOMClassInfo::GetJSClass()
|
||||
{
|
||||
return Jsvalify(&mData->mClass);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
@@ -762,7 +756,7 @@ nsDOMClassInfo::Resolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj));
|
||||
|
||||
JS::Rooted<JS::PropertyDescriptor> desc(cx);
|
||||
if (!JS_GetPropertyDescriptor(cx, global, mData->mClass.name, &desc)) {
|
||||
if (!JS_GetPropertyDescriptor(cx, global, mData->mName, &desc)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@@ -865,7 +859,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
||||
if (if_info) {
|
||||
nsXPIDLCString name;
|
||||
if_info->GetName(getter_Copies(name));
|
||||
NS_ASSERTION(nsCRT::strcmp(CutPrefix(name), mData->mClass.name) == 0,
|
||||
NS_ASSERTION(nsCRT::strcmp(CutPrefix(name), mData->mName) == 0,
|
||||
"Class name and proto chain interface name mismatch!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ typedef nsresult (*nsDOMConstructorFunc)(nsISupports** aNewObject);
|
||||
|
||||
struct nsDOMClassInfoData
|
||||
{
|
||||
// The ASCII name is available as mClass.name.
|
||||
// XXX: mName is the same as the name gettable from the callback. This
|
||||
// redundancy should be removed eventually.
|
||||
const char *mName;
|
||||
const char16_t *mNameUTF16;
|
||||
const js::ClassOps mClassOps;
|
||||
const js::Class mClass;
|
||||
|
||||
@@ -337,14 +337,11 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
|
||||
nsMutationReceiver* orig = GetParent() ? GetParent() : this;
|
||||
if (Observer()->GetReceiverFor(aChild, false, false) != orig) {
|
||||
bool transientExists = false;
|
||||
bool isNewEntry = false;
|
||||
nsCOMArray<nsMutationReceiver>* transientReceivers =
|
||||
Observer()->mTransientReceivers.LookupForAdd(aChild).OrInsert(
|
||||
[&isNewEntry] () {
|
||||
isNewEntry = true;
|
||||
return new nsCOMArray<nsMutationReceiver>();
|
||||
});
|
||||
if (!isNewEntry) {
|
||||
nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr;
|
||||
Observer()->mTransientReceivers.Get(aChild, &transientReceivers);
|
||||
if (!transientReceivers) {
|
||||
transientReceivers = new nsCOMArray<nsMutationReceiver>();
|
||||
Observer()->mTransientReceivers.Put(aChild, transientReceivers);
|
||||
} else {
|
||||
for (int32_t i = 0; i < transientReceivers->Count(); ++i) {
|
||||
nsMutationReceiver* r = transientReceivers->ObjectAt(i);
|
||||
@@ -1113,9 +1110,12 @@ nsAutoMutationBatch::Done()
|
||||
}
|
||||
|
||||
if (allObservers.Length()) {
|
||||
nsCOMArray<nsMutationReceiver>* transientReceivers =
|
||||
ob->mTransientReceivers.LookupForAdd(removed).OrInsert(
|
||||
[] () { return new nsCOMArray<nsMutationReceiver>(); });
|
||||
nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr;
|
||||
ob->mTransientReceivers.Get(removed, &transientReceivers);
|
||||
if (!transientReceivers) {
|
||||
transientReceivers = new nsCOMArray<nsMutationReceiver>();
|
||||
ob->mTransientReceivers.Put(removed, transientReceivers);
|
||||
}
|
||||
for (uint32_t k = 0; k < allObservers.Length(); ++k) {
|
||||
nsMutationReceiver* r = allObservers[k];
|
||||
nsMutationReceiver* orig = r->GetParent() ? r->GetParent() : r;
|
||||
|
||||
@@ -691,15 +691,16 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
||||
return resource->mDocument;
|
||||
}
|
||||
|
||||
RefPtr<PendingLoad>& loadEntry = mPendingLoads.GetOrInsert(clone);
|
||||
if (loadEntry) {
|
||||
RefPtr<PendingLoad> load(loadEntry);
|
||||
RefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(clone, getter_AddRefs(load));
|
||||
if (load) {
|
||||
load.forget(aPendingLoad);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PendingLoad> load(new PendingLoad(aDisplayDocument));
|
||||
loadEntry = load;
|
||||
load = new PendingLoad(aDisplayDocument);
|
||||
|
||||
mPendingLoads.Put(clone, load);
|
||||
|
||||
if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) {
|
||||
// Make sure we don't thrash things by trying this load again, since
|
||||
@@ -822,7 +823,8 @@ nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
|
||||
"Must have both or neither");
|
||||
|
||||
RefPtr<PendingLoad> load;
|
||||
mPendingLoads.Remove(aURI, getter_AddRefs(load));
|
||||
mPendingLoads.Get(aURI, getter_AddRefs(load));
|
||||
mPendingLoads.Remove(aURI);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
||||
@@ -180,7 +180,6 @@ static const char* kObservedPrefs[] = {
|
||||
};
|
||||
|
||||
nsFocusManager::nsFocusManager()
|
||||
: mEventHandlingNeedsFlush(false)
|
||||
{ }
|
||||
|
||||
nsFocusManager::~nsFocusManager()
|
||||
@@ -1574,7 +1573,6 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags)
|
||||
}
|
||||
|
||||
// Make sure that our frames are up to date
|
||||
mEventHandlingNeedsFlush = false;
|
||||
doc->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
nsIPresShell *shell = doc->GetShell();
|
||||
@@ -4222,13 +4220,6 @@ nsFocusManager::MarkUncollectableForCCGeneration(uint32_t aGeneration)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsFocusManager::CanSkipFocus(nsIContent* aContent)
|
||||
{
|
||||
return mFocusedContent == aContent &&
|
||||
(!aContent || !nsContentUtils::IsChromeDoc(aContent->OwnerDoc()));
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewFocusManager(nsIFocusManager** aResult)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define nsFocusManager_h___
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFocusManager.h"
|
||||
#include "nsIObserver.h"
|
||||
@@ -93,26 +92,6 @@ public:
|
||||
return handlingDocument.forget();
|
||||
}
|
||||
|
||||
void NeedsFlushBeforeEventHandling(nsIContent* aContent)
|
||||
{
|
||||
if (mFocusedContent == aContent) {
|
||||
mEventHandlingNeedsFlush = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CanSkipFocus(nsIContent* aContent);
|
||||
|
||||
void FlushBeforeEventHandlingIfNeeded(nsIContent* aContent)
|
||||
{
|
||||
if (mEventHandlingNeedsFlush) {
|
||||
nsCOMPtr<nsIDocument> doc = aContent->GetComposedDoc();
|
||||
if (doc) {
|
||||
mEventHandlingNeedsFlush = false;
|
||||
doc->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the caret with current mode (whether in caret browsing mode or not).
|
||||
*/
|
||||
@@ -656,10 +635,6 @@ private:
|
||||
// moving focus.
|
||||
nsCOMPtr<nsIDocument> mMouseButtonEventHandlingDocument;
|
||||
|
||||
// If set to true, layout of the document of the event target should be
|
||||
// flushed before handling focus depending events.
|
||||
bool mEventHandlingNeedsFlush;
|
||||
|
||||
static bool sTestMode;
|
||||
|
||||
// the single focus manager
|
||||
|
||||
@@ -1854,7 +1854,7 @@ nsMessageManagerScriptExecutor::InitChildGlobalInternal(
|
||||
const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES;
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setSystemZone();
|
||||
options.creationOptions().setZone(JS::SystemZone);
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
|
||||
if (xpc::SharedMemoryEnabled()) {
|
||||
|
||||
@@ -503,9 +503,6 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
|
||||
SetFlags(NODE_CHROME_ONLY_ACCESS);
|
||||
}
|
||||
if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) {
|
||||
aParent->SetMayHaveAnonymousChildren();
|
||||
}
|
||||
if (aParent->IsInShadowTree()) {
|
||||
ClearSubtreeRootPointer();
|
||||
SetFlags(NODE_IS_IN_SHADOW_TREE);
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError) override
|
||||
mozilla::ErrorResult& aError) override
|
||||
{
|
||||
GetNodeValue(aTextContent);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ GK_ATOM(animations, "animations")
|
||||
GK_ATOM(anonid, "anonid")
|
||||
GK_ATOM(anonlocation, "anonlocation")
|
||||
GK_ATOM(any, "any")
|
||||
GK_ATOM(any_hover, "any-hover")
|
||||
GK_ATOM(any_pointer, "any-pointer")
|
||||
GK_ATOM(applet, "applet")
|
||||
GK_ATOM(applyImports, "apply-imports")
|
||||
GK_ATOM(applyTemplates, "apply-templates")
|
||||
@@ -1533,6 +1535,7 @@ GK_ATOM(patternContentUnits, "patternContentUnits")
|
||||
GK_ATOM(patternTransform, "patternTransform")
|
||||
GK_ATOM(patternUnits, "patternUnits")
|
||||
GK_ATOM(pc, "pc")
|
||||
GK_ATOM(pointer, "pointer")
|
||||
GK_ATOM(pointer_events, "pointer-events")
|
||||
GK_ATOM(points, "points")
|
||||
GK_ATOM(pointsAtX, "pointsAtX")
|
||||
|
||||
+33
-52
@@ -538,7 +538,7 @@ DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope,
|
||||
|
||||
class IdleRequestExecutor final : public nsIRunnable
|
||||
, public nsICancelableRunnable
|
||||
, public nsIIdleRunnable
|
||||
, public nsIIncrementalRunnable
|
||||
{
|
||||
public:
|
||||
explicit IdleRequestExecutor(nsGlobalWindow* aWindow)
|
||||
@@ -582,7 +582,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIncrementalRunnable)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
@@ -1026,7 +1026,7 @@ protected:
|
||||
static nsGlobalWindow* GetOuterWindow(JSObject *proxy)
|
||||
{
|
||||
nsGlobalWindow* outerWindow = nsGlobalWindow::FromSupports(
|
||||
static_cast<nsISupports*>(js::GetProxyReservedSlot(proxy, 0).toPrivate()));
|
||||
static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate()));
|
||||
MOZ_ASSERT_IF(outerWindow, outerWindow->IsOuterWindow());
|
||||
return outerWindow;
|
||||
}
|
||||
@@ -1053,12 +1053,9 @@ static const js::ClassExtension OuterWindowProxyClassExtension = PROXY_MAKE_EXT(
|
||||
nsOuterWindowProxy::ObjectMoved
|
||||
);
|
||||
|
||||
// Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
|
||||
// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
|
||||
// malloc.
|
||||
const js::Class OuterWindowProxyClass = PROXY_CLASS_WITH_EXT(
|
||||
"Proxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2), /* additional class flags */
|
||||
0, /* additional class flags */
|
||||
&OuterWindowProxyClassExtension);
|
||||
|
||||
const char *
|
||||
@@ -1074,7 +1071,7 @@ nsOuterWindowProxy::finalize(JSFreeOp *fop, JSObject *proxy) const
|
||||
{
|
||||
nsGlobalWindow* outerWindow = GetOuterWindow(proxy);
|
||||
if (outerWindow) {
|
||||
outerWindow->ClearWrapper(proxy);
|
||||
outerWindow->ClearWrapper();
|
||||
|
||||
// Ideally we would use OnFinalize here, but it's possible that
|
||||
// EnsureScriptEnvironment will later be called on the window, and we don't
|
||||
@@ -1482,7 +1479,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
||||
#endif
|
||||
mNotifiedIDDestroyed(false),
|
||||
mAllowScriptsToClose(false),
|
||||
mTopLevelOuterContentWindow(false),
|
||||
mTimeoutInsertionPoint(nullptr),
|
||||
mTimeoutIdCounter(1),
|
||||
mTimeoutFiringDepth(0),
|
||||
@@ -1686,9 +1682,9 @@ nsGlobalWindow::~nsGlobalWindow()
|
||||
("DOMWINDOW %p destroyed", this));
|
||||
|
||||
if (IsOuterWindow()) {
|
||||
JSObject *proxy = GetWrapperMaybeDead();
|
||||
JSObject *proxy = GetWrapperPreserveColor();
|
||||
if (proxy) {
|
||||
js::SetProxyReservedSlot(proxy, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyExtra(proxy, 0, js::PrivateValue(nullptr));
|
||||
}
|
||||
|
||||
// An outer window is destroyed with inner windows still possibly
|
||||
@@ -2776,7 +2772,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
||||
}
|
||||
|
||||
if (top && top->GetGlobalJSObject()) {
|
||||
options.creationOptions().setExistingZone(top->GetGlobalJSObject());
|
||||
options.creationOptions().setSameZoneAs(top->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
options.creationOptions().setSecureContext(aIsSecureContext);
|
||||
@@ -2861,7 +2857,9 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
// transplanting code, since it has no good way to handle errors. This uses
|
||||
// the untrusted script limit, which is not strictly necessary since no
|
||||
// actual script should run.
|
||||
if (!js::CheckRecursionLimitConservativeDontReport(cx)) {
|
||||
bool overrecursed = false;
|
||||
JS_CHECK_RECURSION_CONSERVATIVE_DONT_REPORT(cx, overrecursed = true);
|
||||
if (overrecursed) {
|
||||
NS_WARNING("Overrecursion in SetNewDocument");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@@ -3049,7 +3047,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
|
||||
NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE);
|
||||
|
||||
js::SetProxyReservedSlot(outer, 0, js::PrivateValue(ToSupports(this)));
|
||||
js::SetProxyExtra(outer, 0, js::PrivateValue(ToSupports(this)));
|
||||
|
||||
// Inform the nsJSContext, which is the canonical holder of the outer.
|
||||
mContext->SetWindowProxy(outer);
|
||||
@@ -3067,8 +3065,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, GetWrapperPreserveColor());
|
||||
|
||||
js::SetProxyReservedSlot(obj, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyExtra(obj, 0, js::PrivateValue(nullptr));
|
||||
js::SetProxyExtra(outerObject, 0, js::PrivateValue(nullptr));
|
||||
|
||||
outerObject = xpc::TransplantObject(cx, obj, outerObject);
|
||||
if (!outerObject) {
|
||||
@@ -3076,7 +3074,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(ToSupports(this)));
|
||||
js::SetProxyExtra(outerObject, 0, js::PrivateValue(ToSupports(this)));
|
||||
|
||||
SetWrapper(outerObject);
|
||||
|
||||
@@ -3193,7 +3191,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
newInnerWindow->mChromeEventHandler = mChromeEventHandler;
|
||||
}
|
||||
|
||||
nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT, GetWrapperPreserveColor());
|
||||
nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT);
|
||||
kungFuDeathGrip->DidInitializeContext();
|
||||
|
||||
// We wait to fire the debugger hook until the window is all set up and hooked
|
||||
@@ -3338,9 +3336,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
|
||||
MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup || mTabGroup == Cast(parentWindow)->mTabGroup);
|
||||
|
||||
mTopLevelOuterContentWindow =
|
||||
!mIsChrome && GetScriptableTopInternal() == this;
|
||||
|
||||
NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
|
||||
|
||||
if (mFrames) {
|
||||
@@ -3422,12 +3417,7 @@ nsGlobalWindow::DetachFromDocShell()
|
||||
mChromeEventHandler = nullptr; // force release now
|
||||
|
||||
if (mContext) {
|
||||
// When we're about to destroy a top level content window
|
||||
// (for example a tab), we trigger a full GC by passing null as the last
|
||||
// param. We also trigger a full GC for chrome windows.
|
||||
nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL,
|
||||
(mTopLevelOuterContentWindow || mIsChrome) ?
|
||||
nullptr : GetWrapperPreserveColor());
|
||||
nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL);
|
||||
mContext = nullptr;
|
||||
}
|
||||
|
||||
@@ -3821,7 +3811,7 @@ void
|
||||
nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
if (aObject == GetWrapperMaybeDead()) {
|
||||
if (aObject == GetWrapperPreserveColor()) {
|
||||
PoisonWrapper();
|
||||
}
|
||||
}
|
||||
@@ -9419,23 +9409,13 @@ public:
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
|
||||
// We only want to nuke wrappers for the chrome->content case
|
||||
if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
|
||||
JSCompartment* cpt = js::GetObjectCompartment(obj);
|
||||
nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
|
||||
|
||||
nsAutoString addonId;
|
||||
if (NS_SUCCEEDED(pc->GetAddonId(addonId)) && !addonId.IsEmpty()) {
|
||||
// We want to nuke all references to the add-on compartment.
|
||||
xpc::NukeAllWrappersForCompartment(cx, cpt,
|
||||
win->IsInnerWindow() ? js::DontNukeWindowReferences
|
||||
: js::NukeWindowReferences);
|
||||
} else {
|
||||
// We only want to nuke wrappers for the chrome->content case
|
||||
js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
|
||||
win->IsInnerWindow() ? js::DontNukeWindowReferences
|
||||
: js::NukeWindowReferences,
|
||||
js::NukeIncomingReferences);
|
||||
}
|
||||
js::NukeCrossCompartmentWrappers(cx,
|
||||
BrowserCompartmentMatcher(),
|
||||
js::SingleCompartment(js::GetObjectCompartment(obj)),
|
||||
win->IsInnerWindow() ? js::DontNukeWindowReferences
|
||||
: js::NukeWindowReferences);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14389,16 +14369,17 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
|
||||
|
||||
nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this);
|
||||
nsCOMPtr<nsIMessageBroadcaster> messageManager =
|
||||
myself->mGroupMessageManagers.Get(aGroup);
|
||||
|
||||
myself->mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
|
||||
[this, &aError] () {
|
||||
nsFrameMessageManager* parent =
|
||||
static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
|
||||
if (!messageManager) {
|
||||
nsFrameMessageManager* parent =
|
||||
static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
|
||||
|
||||
return new nsFrameMessageManager(nullptr,
|
||||
parent,
|
||||
MM_CHROME | MM_BROADCASTER);
|
||||
});
|
||||
messageManager = new nsFrameMessageManager(nullptr,
|
||||
parent,
|
||||
MM_CHROME | MM_BROADCASTER);
|
||||
myself->mGroupMessageManagers.Put(aGroup, messageManager);
|
||||
}
|
||||
|
||||
return messageManager;
|
||||
}
|
||||
|
||||
@@ -1800,8 +1800,6 @@ protected:
|
||||
// even if "dom.allow_scripts_to_close_windows" is false.
|
||||
bool mAllowScriptsToClose : 1;
|
||||
|
||||
bool mTopLevelOuterContentWindow : 1;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
nsWeakPtr mOpener;
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
|
||||
+10
-11
@@ -1,5 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@@ -10,21 +9,21 @@
|
||||
#include "nsIXPCScriptable.h"
|
||||
|
||||
#define DOM_BASE_SCRIPTABLE_FLAGS \
|
||||
(XPC_SCRIPTABLE_USE_JSSTUB_FOR_ADDPROPERTY | \
|
||||
XPC_SCRIPTABLE_USE_JSSTUB_FOR_DELPROPERTY | \
|
||||
XPC_SCRIPTABLE_USE_JSSTUB_FOR_SETPROPERTY | \
|
||||
XPC_SCRIPTABLE_ALLOW_PROP_MODS_TO_PROTOTYPE | \
|
||||
XPC_SCRIPTABLE_DONT_ASK_INSTANCE_FOR_SCRIPTABLE | \
|
||||
XPC_SCRIPTABLE_DONT_REFLECT_INTERFACE_NAMES)
|
||||
(nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY | \
|
||||
nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
|
||||
nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE | \
|
||||
nsIXPCScriptable::DONT_ASK_INSTANCE_FOR_SCRIPTABLE | \
|
||||
nsIXPCScriptable::DONT_REFLECT_INTERFACE_NAMES)
|
||||
|
||||
#define DEFAULT_SCRIPTABLE_FLAGS \
|
||||
(DOM_BASE_SCRIPTABLE_FLAGS | \
|
||||
XPC_SCRIPTABLE_WANT_RESOLVE | \
|
||||
XPC_SCRIPTABLE_WANT_PRECREATE)
|
||||
nsIXPCScriptable::WANT_RESOLVE | \
|
||||
nsIXPCScriptable::WANT_PRECREATE)
|
||||
|
||||
#define DOM_DEFAULT_SCRIPTABLE_FLAGS \
|
||||
(DEFAULT_SCRIPTABLE_FLAGS | \
|
||||
XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE | \
|
||||
XPC_SCRIPTABLE_CLASSINFO_INTERFACES_ONLY)
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
|
||||
|
||||
#endif /* nsIDOMClassInfo_h___ */
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
@@ -420,7 +421,7 @@ nsINode::ChildNodes()
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::GetTextContentInternal(nsAString& aTextContent, OOMReporter& aError)
|
||||
nsINode::GetTextContentInternal(nsAString& aTextContent, ErrorResult& aError)
|
||||
{
|
||||
SetDOMStringToNull(aTextContent);
|
||||
}
|
||||
|
||||
+2
-8
@@ -1335,7 +1335,7 @@ protected:
|
||||
|
||||
public:
|
||||
void GetTextContent(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError)
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
GetTextContentInternal(aTextContent, aError);
|
||||
}
|
||||
@@ -1593,9 +1593,6 @@ private:
|
||||
ParserHasNotified,
|
||||
// Sets if the node is apz aware or we have apz aware listeners.
|
||||
MayBeApzAware,
|
||||
// Set if the element might have any kind of anonymous content children,
|
||||
// which would not be found through the element's children list.
|
||||
ElementMayHaveAnonymousChildren,
|
||||
// Set if this node has at some point (and may still have)
|
||||
// display:none or display:contents children.
|
||||
NodeMayHaveChildrenWithLayoutBoxesDisabled,
|
||||
@@ -1738,9 +1735,6 @@ public:
|
||||
return GetBoolFlag(MayBeApzAware);
|
||||
}
|
||||
|
||||
void SetMayHaveAnonymousChildren() { SetBoolFlag(ElementMayHaveAnonymousChildren); }
|
||||
bool MayHaveAnonymousChildren() const { return GetBoolFlag(ElementMayHaveAnonymousChildren); }
|
||||
|
||||
void SetMayHaveChildrenWithLayoutBoxesDisabled()
|
||||
{
|
||||
SetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled);
|
||||
@@ -1977,7 +1971,7 @@ protected:
|
||||
}
|
||||
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError);
|
||||
mozilla::ErrorResult& aError);
|
||||
virtual void SetTextContentInternal(const nsAString& aTextContent,
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
|
||||
+241
-451
File diff suppressed because it is too large.
Load diff
@@ -14,7 +14,6 @@
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
@@ -91,7 +90,7 @@ public:
|
||||
int32_t aExtraForgetSkippableCalls = 0);
|
||||
|
||||
// Run a cycle collector slice, using a heuristic to decide how long to run it.
|
||||
static void RunCycleCollectorSlice(mozilla::TimeStamp aDeadline);
|
||||
static void RunCycleCollectorSlice();
|
||||
|
||||
// Run a cycle collector slice, using the given work budget.
|
||||
static void RunCycleCollectorWorkSlice(int64_t aWorkBudget);
|
||||
@@ -105,18 +104,17 @@ public:
|
||||
|
||||
static void RunNextCollectorTimer();
|
||||
|
||||
// The GC should probably run soon, in the zone of object aObj (if given).
|
||||
static void PokeGC(JS::gcreason::Reason aReason, JSObject* aObj, int aDelay = 0);
|
||||
static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0);
|
||||
static void KillGCTimer();
|
||||
|
||||
static void PokeShrinkingGC();
|
||||
static void KillShrinkingGCTimer();
|
||||
|
||||
static void MaybePokeCC();
|
||||
static void KillCCRunner();
|
||||
static void KillICCRunner();
|
||||
static void KillCCTimer();
|
||||
static void KillICCTimer();
|
||||
static void KillFullGCTimer();
|
||||
static void KillInterSliceGCRunner();
|
||||
static void KillInterSliceGCTimer();
|
||||
|
||||
// Calling LikelyShortLivingObjectCreated() makes a GC more likely.
|
||||
static void LikelyShortLivingObjectCreated();
|
||||
@@ -131,6 +129,7 @@ public:
|
||||
return global ? mGlobalObjectRef.get() : nullptr;
|
||||
}
|
||||
|
||||
static void NotifyDidPaint();
|
||||
protected:
|
||||
virtual ~nsJSContext();
|
||||
|
||||
|
||||
@@ -313,8 +313,8 @@ nsWindowRoot::GetEnabledDisabledCommandsForControllers(nsIControllers* aControll
|
||||
// Use a hash to determine which commands have already been handled by
|
||||
// earlier controllers, as the earlier controller's result should get
|
||||
// priority.
|
||||
if (aCommandsHandled.EnsureInserted(commands[e])) {
|
||||
// We inserted a new entry into aCommandsHandled.
|
||||
if (!aCommandsHandled.Contains(commands[e])) {
|
||||
aCommandsHandled.PutEntry(commands[e]);
|
||||
|
||||
bool enabled = false;
|
||||
controller->IsCommandEnabled(commands[e], &enabled);
|
||||
|
||||
+11
-28
@@ -95,25 +95,12 @@ public:
|
||||
* object returned is not guaranteed to be kept alive past the next CC.
|
||||
*
|
||||
* This should only be called if you are certain that the return value won't
|
||||
* be passed into a JSAPI function and that it won't be stored without being
|
||||
* be passed into a JS API function and that it won't be stored without being
|
||||
* rooted (or otherwise signaling the stored value to the CC).
|
||||
*/
|
||||
JSObject* GetWrapperPreserveColor() const;
|
||||
|
||||
/**
|
||||
* Get the cached wrapper.
|
||||
*
|
||||
* This getter does not check whether the wrapper is dead and in the process
|
||||
* of being finalized.
|
||||
*
|
||||
* This should only be called if you really need to see the raw contents of
|
||||
* this cache, for example as part of finalization. Don't store the result
|
||||
* anywhere or pass it into JSAPI functions that may cause the value to
|
||||
* escape.
|
||||
*/
|
||||
JSObject* GetWrapperMaybeDead() const
|
||||
JSObject* GetWrapperPreserveColor() const
|
||||
{
|
||||
return mWrapper;
|
||||
return GetWrapperJSObject();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -134,23 +121,14 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
* Clear the wrapper. This should be called from the finalizer for the
|
||||
* wrapper.
|
||||
*/
|
||||
void ClearWrapper()
|
||||
{
|
||||
MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
|
||||
SetWrapperJSObject(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache if it still contains a specific wrapper object. This should
|
||||
* be called from the finalizer for the wrapper.
|
||||
*/
|
||||
void ClearWrapper(JSObject* obj)
|
||||
{
|
||||
if (obj == mWrapper) {
|
||||
ClearWrapper();
|
||||
}
|
||||
SetWrapperJSObject(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,6 +288,11 @@ private:
|
||||
SetWrapperFlags(WRAPPER_IS_NOT_DOM_BINDING);
|
||||
}
|
||||
|
||||
JSObject *GetWrapperJSObject() const
|
||||
{
|
||||
return mWrapper;
|
||||
}
|
||||
|
||||
void SetWrapperJSObject(JSObject* aWrapper);
|
||||
|
||||
FlagsType GetWrapperFlags() const
|
||||
|
||||
@@ -10,21 +10,6 @@
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/TracingAPI.h"
|
||||
|
||||
inline JSObject*
|
||||
nsWrapperCache::GetWrapperPreserveColor() const
|
||||
{
|
||||
JSObject* obj = mWrapper;
|
||||
if (obj && js::gc::EdgeNeedsSweepUnbarriered(&obj)) {
|
||||
// The object has been found to be dead and is in the process of being
|
||||
// finalized, so don't let the caller see it. As an optimisation, remove it
|
||||
// from the cache so we don't have to do this check in future.
|
||||
const_cast<nsWrapperCache*>(this)->ClearWrapper();
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(obj == mWrapper);
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline JSObject*
|
||||
nsWrapperCache::GetWrapper() const
|
||||
{
|
||||
|
||||
@@ -2118,10 +2118,7 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg, ErrorResult& aErr
|
||||
// the untrusted script limit, which is not strictly necessary since no
|
||||
// actual script should run.
|
||||
// TODO: Make sure to retain 'onerror' if bug 1342439 lands.
|
||||
if (!js::CheckRecursionLimitConservative(aCx)) {
|
||||
aError.StealExceptionFromJSContext(aCx);
|
||||
return;
|
||||
}
|
||||
JS_CHECK_RECURSION_CONSERVATIVE(aCx, aError.StealExceptionFromJSContext(aCx); return);
|
||||
|
||||
JS::Rooted<JSObject*> aObj(aCx, aObjArg);
|
||||
const DOMJSClass* domClass = GetDOMClass(aObj);
|
||||
@@ -2209,9 +2206,9 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg, ErrorResult& aErr
|
||||
// NB: It's important to do this _after_ copying the properties to
|
||||
// propertyHolder. Otherwise, an object with |foo.x === foo| will
|
||||
// crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
|
||||
js::SetReservedSlot(newobj, DOM_OBJECT_SLOT,
|
||||
js::GetReservedSlot(aObj, DOM_OBJECT_SLOT));
|
||||
js::SetReservedSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
js::SetReservedOrProxyPrivateSlot(newobj, DOM_OBJECT_SLOT,
|
||||
js::GetReservedOrProxyPrivateSlot(aObj, DOM_OBJECT_SLOT));
|
||||
js::SetReservedOrProxyPrivateSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
|
||||
aObj = xpc::TransplantObject(aCx, aObj, newobj);
|
||||
if (!aObj) {
|
||||
|
||||
+50
-45
@@ -153,7 +153,7 @@ UnwrapDOMObject(JSObject* obj)
|
||||
MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
|
||||
"Don't pass non-DOM objects to this function");
|
||||
|
||||
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
|
||||
JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
|
||||
return static_cast<T*>(val.toPrivate());
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ UnwrapPossiblyNotInitializedDOMObject(JSObject* obj)
|
||||
MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
|
||||
"Don't pass non-DOM objects to this function");
|
||||
|
||||
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
|
||||
JS::Value val = js::GetReservedOrProxyPrivateSlot(obj, DOM_OBJECT_SLOT);
|
||||
if (val.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1032,22 +1032,19 @@ MaybeWrapNonDOMObjectOrNullValue(JSContext* cx, JS::MutableHandle<JS::Value> rva
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
|
||||
{
|
||||
if (rval.isGCThing()) {
|
||||
if (rval.isString()) {
|
||||
return MaybeWrapStringValue(cx, rval);
|
||||
}
|
||||
if (rval.isObject()) {
|
||||
return MaybeWrapObjectValue(cx, rval);
|
||||
}
|
||||
// This could be optimized by checking the zone first, similar to
|
||||
// the way strings are handled. At present, this is used primarily
|
||||
// for structured cloning, so avoiding the overhead of JS_WrapValue
|
||||
// calls is less important than for other types.
|
||||
if (rval.isBigInt()) {
|
||||
return JS_WrapValue(cx, rval);
|
||||
}
|
||||
MOZ_ASSERT(rval.isSymbol());
|
||||
JS_MarkCrossZoneId(cx, SYMBOL_TO_JSID(rval.toSymbol()));
|
||||
if (rval.isString()) {
|
||||
return MaybeWrapStringValue(cx, rval);
|
||||
}
|
||||
|
||||
if (rval.isObject()) {
|
||||
return MaybeWrapObjectValue(cx, rval);
|
||||
}
|
||||
// This could be optimized by checking the zone first, similar to
|
||||
// the way strings are handled. At present, this is used primarily
|
||||
// for structured cloning, so avoiding the overhead of JS_WrapValue
|
||||
// calls is less important than for other types.
|
||||
if (rval.isBigInt()) {
|
||||
return JS_WrapValue(cx, rval);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1541,27 +1538,25 @@ GetUseXBLScope(const ParentObject& aParentObject)
|
||||
|
||||
template<class T>
|
||||
inline void
|
||||
ClearWrapper(T* p, nsWrapperCache* cache, JSObject* obj)
|
||||
ClearWrapper(T* p, nsWrapperCache* cache)
|
||||
{
|
||||
JS::AutoAssertGCCallback inCallback;
|
||||
cache->ClearWrapper(obj);
|
||||
cache->ClearWrapper();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void
|
||||
ClearWrapper(T* p, void*, JSObject* obj)
|
||||
ClearWrapper(T* p, void*)
|
||||
{
|
||||
JS::AutoAssertGCCallback inCallback;
|
||||
nsWrapperCache* cache;
|
||||
CallQueryInterface(p, &cache);
|
||||
ClearWrapper(p, cache, obj);
|
||||
ClearWrapper(p, cache);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void
|
||||
UpdateWrapper(T* p, nsWrapperCache* cache, JSObject* obj, const JSObject* old)
|
||||
{
|
||||
JS::AutoAssertGCCallback inCallback;
|
||||
JS::AutoAssertGCCallback inCallback(obj);
|
||||
cache->UpdateWrapper(obj, old);
|
||||
}
|
||||
|
||||
@@ -1569,7 +1564,7 @@ template<class T>
|
||||
inline void
|
||||
UpdateWrapper(T* p, void*, JSObject* obj, const JSObject* old)
|
||||
{
|
||||
JS::AutoAssertGCCallback inCallback;
|
||||
JS::AutoAssertGCCallback inCallback(obj);
|
||||
nsWrapperCache* cache;
|
||||
CallQueryInterface(p, &cache);
|
||||
UpdateWrapper(p, cache, obj, old);
|
||||
@@ -1756,7 +1751,7 @@ struct WrapNativeHelper
|
||||
JSObject* obj;
|
||||
if ((obj = cache->GetWrapper())) {
|
||||
// GetWrapper always unmarks gray.
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -1764,11 +1759,11 @@ struct WrapNativeHelper
|
||||
if (!CouldBeDOMBinding(parent)) {
|
||||
// WrapNativeFallback never returns a gray thing.
|
||||
obj = WrapNativeFallback<T>::Wrap(cx, parent, cache);
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
|
||||
} else {
|
||||
// WrapObject never returns a gray thing.
|
||||
obj = parent->WrapObject(cx, nullptr);
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
|
||||
}
|
||||
|
||||
return obj;
|
||||
@@ -1790,12 +1785,12 @@ struct WrapNativeHelper<T, false>
|
||||
"Unexpected object in nsWrapperCache");
|
||||
obj = rootedObj;
|
||||
#endif
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj = WrapNativeISupports(cx, parent, cache);
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT_IF(obj, !JS::ObjectIsMarkedGray(obj));
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
@@ -1814,7 +1809,7 @@ FindAssociatedGlobal(JSContext* cx, T* p, nsWrapperCache* cache,
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(obj));
|
||||
MOZ_ASSERT(!JS::ObjectIsMarkedGray(obj));
|
||||
|
||||
obj = js::GetGlobalForObjectCrossCompartment(obj);
|
||||
|
||||
@@ -1831,7 +1826,7 @@ FindAssociatedGlobal(JSContext* cx, T* p, nsWrapperCache* cache,
|
||||
JS::Rooted<JSObject*> rootedObj(cx, obj);
|
||||
JSObject* xblScope = xpc::GetXBLScope(cx, rootedObj);
|
||||
MOZ_ASSERT_IF(xblScope, JS_IsGlobalObject(xblScope));
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(xblScope));
|
||||
MOZ_ASSERT_IF(xblScope, !JS::ObjectIsMarkedGray(xblScope));
|
||||
return xblScope;
|
||||
}
|
||||
|
||||
@@ -1956,9 +1951,9 @@ GetOrCreateDOMReflectorNoWrap(JSContext* cx, T& value,
|
||||
|
||||
template <class T>
|
||||
inline JSObject*
|
||||
GetCallbackFromCallbackObject(JSContext* aCx, T* aObj)
|
||||
GetCallbackFromCallbackObject(T* aObj)
|
||||
{
|
||||
return aObj->Callback(aCx);
|
||||
return aObj->Callback();
|
||||
}
|
||||
|
||||
// Helper for getting the callback JSObject* of a smart ptr around a
|
||||
@@ -1967,26 +1962,26 @@ GetCallbackFromCallbackObject(JSContext* aCx, T* aObj)
|
||||
template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
|
||||
struct GetCallbackFromCallbackObjectHelper
|
||||
{
|
||||
static inline JSObject* Get(JSContext* aCx, const T& aObj)
|
||||
static inline JSObject* Get(const T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObject(aCx, aObj.get());
|
||||
return GetCallbackFromCallbackObject(aObj.get());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GetCallbackFromCallbackObjectHelper<T, false>
|
||||
{
|
||||
static inline JSObject* Get(JSContext* aCx, T& aObj)
|
||||
static inline JSObject* Get(T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObject(aCx, &aObj);
|
||||
return GetCallbackFromCallbackObject(&aObj);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline JSObject*
|
||||
GetCallbackFromCallbackObject(JSContext* aCx, T& aObj)
|
||||
GetCallbackFromCallbackObject(T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObjectHelper<T>::Get(aCx, aObj);
|
||||
return GetCallbackFromCallbackObjectHelper<T>::Get(aObj);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -2079,6 +2074,16 @@ AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
nsTArray<nsString>& names,
|
||||
bool shadowPrototypeProperties, JS::AutoIdVector& props);
|
||||
|
||||
namespace binding_detail {
|
||||
|
||||
class FastErrorResult :
|
||||
public mozilla::binding_danger::TErrorResult<
|
||||
mozilla::binding_danger::JustAssertCleanupPolicy>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace binding_detail
|
||||
|
||||
enum StringificationBehavior {
|
||||
eStringify,
|
||||
eEmpty,
|
||||
@@ -2902,7 +2907,8 @@ public:
|
||||
~BindingJSObjectCreator()
|
||||
{
|
||||
if (mReflector) {
|
||||
js::SetReservedSlot(mReflector, DOM_OBJECT_SLOT, JS::UndefinedValue());
|
||||
js::SetReservedOrProxyPrivateSlot(mReflector, DOM_OBJECT_SLOT,
|
||||
JS::UndefinedValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2910,15 +2916,14 @@ public:
|
||||
CreateProxyObject(JSContext* aCx, const js::Class* aClass,
|
||||
const DOMProxyHandler* aHandler,
|
||||
JS::Handle<JSObject*> aProto, T* aNative,
|
||||
JS::Handle<JS::Value> aExpandoValue,
|
||||
JS::MutableHandle<JSObject*> aReflector)
|
||||
{
|
||||
js::ProxyOptions options;
|
||||
options.setClass(aClass);
|
||||
aReflector.set(js::NewProxyObject(aCx, aHandler, aExpandoValue, aProto,
|
||||
JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
|
||||
aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
|
||||
options));
|
||||
if (aReflector) {
|
||||
js::SetProxyReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
|
||||
mNative = aNative;
|
||||
mReflector = aReflector;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
JS::Handle<JSObject*> CallableOrNull() const
|
||||
JS::Handle<JSObject*> Callable() const
|
||||
{
|
||||
return CallbackOrNull();
|
||||
return Callback();
|
||||
}
|
||||
|
||||
JS::Handle<JSObject*> CallablePreserveColor() const
|
||||
|
||||
@@ -36,44 +36,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
|
||||
tmp->DropJSObjects();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(CallbackObject)
|
||||
JSObject* callback = tmp->CallbackPreserveColor();
|
||||
|
||||
if (!aRemovingAllowed) {
|
||||
// If our callback has been cleared, we can't be part of a garbage cycle.
|
||||
return !callback;
|
||||
}
|
||||
|
||||
// mCallback is always wrapped for the CallbackObject's incumbent global. In
|
||||
// the case where the real callback is in a different compartment, we have a
|
||||
// cross-compartment wrapper, and it will automatically be cut when its
|
||||
// compartment is nuked. In the case where it is in the same compartment, we
|
||||
// have a reference to the real function. Since that means there are no
|
||||
// wrappers to cut, we need to check whether the compartment is still alive,
|
||||
// and drop the references if it is not.
|
||||
|
||||
if (MOZ_UNLIKELY(!callback)) {
|
||||
return true;
|
||||
}
|
||||
auto pvt = xpc::CompartmentPrivate::Get(callback);
|
||||
if (MOZ_LIKELY(tmp->mIncumbentGlobal && pvt) && MOZ_UNLIKELY(pvt->wasNuked)) {
|
||||
// It's not safe to release our global reference or drop our JS objects at
|
||||
// this point, so defer their finalization until CC is finished.
|
||||
AddForDeferredFinalization(new JSObjectsDropper(tmp));
|
||||
DeferredFinalize(tmp->mIncumbentGlobal.forget().take());
|
||||
return true;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(CallbackObject)
|
||||
return !tmp->mCallback;
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(CallbackObject)
|
||||
return !tmp->mCallback;
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
@@ -104,18 +66,6 @@ CallbackObject::HoldJSObjectsIfMoreThanOneOwner()
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CallbackObject::Callback(JSContext* aCx)
|
||||
{
|
||||
JSObject* callback = CallbackOrNull();
|
||||
if (!callback) {
|
||||
callback = JS_NewDeadWrapper(aCx);
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(callback);
|
||||
return callback;
|
||||
}
|
||||
|
||||
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
|
||||
ErrorResult& aRv,
|
||||
const char* aExecutionReason,
|
||||
@@ -140,14 +90,8 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
|
||||
webIDLCallerPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
|
||||
}
|
||||
|
||||
JSObject* wrappedCallback = aCallback->CallbackPreserveColor();
|
||||
if (!wrappedCallback) {
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
|
||||
NS_LITERAL_CSTRING("Cannot execute callback from a nuked compartment."));
|
||||
return;
|
||||
}
|
||||
// First, find the real underlying callback.
|
||||
JSObject* realCallback = js::UncheckedUnwrap(wrappedCallback);
|
||||
JSObject* realCallback = js::UncheckedUnwrap(aCallback->CallbackPreserveColor());
|
||||
nsIGlobalObject* globalObject = nullptr;
|
||||
|
||||
JSContext* cx;
|
||||
@@ -210,14 +154,13 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
|
||||
|
||||
cx = mAutoEntryScript->cx();
|
||||
|
||||
// Unmark the callable (by invoking CallbackOrNull() and not the
|
||||
// CallbackPreserveColor() variant), and stick it in a Rooted before it can
|
||||
// go gray again.
|
||||
// Unmark the callable (by invoking Callback() and not the CallbackPreserveColor()
|
||||
// variant), and stick it in a Rooted before it can go gray again.
|
||||
// Nothing before us in this function can trigger a CC, so it's safe to wait
|
||||
// until here it do the unmark. This allows us to construct mRootedCallable
|
||||
// with the cx from mAutoEntryScript, avoiding the cost of finding another
|
||||
// JSContext. (Rooted<> does not care about requests or compartments.)
|
||||
mRootedCallable.emplace(cx, aCallback->CallbackOrNull());
|
||||
mRootedCallable.emplace(cx, aCallback->Callback());
|
||||
}
|
||||
|
||||
// JS-implemented WebIDL is always OK to run, since it runs with Chrome
|
||||
@@ -366,10 +309,7 @@ CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::Rooted<JSObject*> callback(cx, aCallback->CallbackOrNull());
|
||||
if (!callback) {
|
||||
return nullptr;
|
||||
}
|
||||
JS::Rooted<JSObject*> callback(cx, aCallback->Callback());
|
||||
|
||||
JSAutoCompartment ac(cx, callback);
|
||||
RefPtr<nsXPCWrappedJS> wrappedJS;
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(DOM_CALLBACKOBJECT_IID)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CallbackObject)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
|
||||
|
||||
// The caller may pass a global object which will act as an override for the
|
||||
// incumbent script settings object when the callback is invoked (overriding
|
||||
@@ -78,24 +78,12 @@ public:
|
||||
Init(aCallback, aAsyncStack, aIncumbentGlobal);
|
||||
}
|
||||
|
||||
// This is guaranteed to be non-null from the time the CallbackObject is
|
||||
// created until JavaScript has had a chance to run. It will only return null
|
||||
// after a JavaScript caller has called nukeSandbox on a Sandbox object, and
|
||||
// the cycle collector has had a chance to run.
|
||||
//
|
||||
// This means that any native callee which receives a CallbackObject as an
|
||||
// argument can safely rely on the callback being non-null so long as it
|
||||
// doesn't trigger any scripts before it accesses it.
|
||||
JS::Handle<JSObject*> CallbackOrNull() const
|
||||
JS::Handle<JSObject*> Callback() const
|
||||
{
|
||||
mCallback.exposeToActiveJS();
|
||||
return CallbackPreserveColor();
|
||||
}
|
||||
|
||||
// Like CallbackOrNull(), but will return a new dead proxy object in the
|
||||
// caller's compartment if the callback is null.
|
||||
JSObject* Callback(JSContext* aCx);
|
||||
|
||||
JSObject* GetCreationStack() const
|
||||
{
|
||||
return mCreationStack;
|
||||
@@ -124,12 +112,12 @@ public:
|
||||
|
||||
/*
|
||||
* If the callback is known to be non-gray, then this method can be
|
||||
* used instead of CallbackOrNull() to avoid the overhead of
|
||||
* used instead of Callback() to avoid the overhead of
|
||||
* ExposeObjectToActiveJS().
|
||||
*/
|
||||
JS::Handle<JSObject*> CallbackKnownNotGray() const
|
||||
{
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(mCallback));
|
||||
MOZ_ASSERT(!JS::ObjectIsMarkedGray(mCallback));
|
||||
return CallbackPreserveColor();
|
||||
}
|
||||
|
||||
@@ -171,33 +159,13 @@ protected:
|
||||
|
||||
bool operator==(const CallbackObject& aOther) const
|
||||
{
|
||||
JSObject* wrappedThis = CallbackPreserveColor();
|
||||
JSObject* wrappedOther = aOther.CallbackPreserveColor();
|
||||
if (!wrappedThis || !wrappedOther) {
|
||||
return this == &aOther;
|
||||
}
|
||||
|
||||
JSObject* thisObj = js::UncheckedUnwrap(wrappedThis);
|
||||
JSObject* otherObj = js::UncheckedUnwrap(wrappedOther);
|
||||
JSObject* thisObj =
|
||||
js::UncheckedUnwrap(CallbackPreserveColor());
|
||||
JSObject* otherObj =
|
||||
js::UncheckedUnwrap(aOther.CallbackPreserveColor());
|
||||
return thisObj == otherObj;
|
||||
}
|
||||
|
||||
class JSObjectsDropper final
|
||||
{
|
||||
public:
|
||||
explicit JSObjectsDropper(CallbackObject* aHolder)
|
||||
: mHolder(aHolder)
|
||||
{}
|
||||
|
||||
~JSObjectsDropper()
|
||||
{
|
||||
mHolder->DropJSObjects();
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<CallbackObject> mHolder;
|
||||
};
|
||||
|
||||
private:
|
||||
inline void InitNoHold(JSObject* aCallback, JSObject* aCreationStack,
|
||||
nsIGlobalObject* aIncumbentGlobal)
|
||||
@@ -520,11 +488,8 @@ public:
|
||||
nsCOMPtr<nsISupports> supp =
|
||||
CallbackObjectHolderBase::ToXPCOMCallback(GetWebIDLCallback(),
|
||||
NS_GET_TEMPLATE_IID(XPCOMCallbackT));
|
||||
if (supp) {
|
||||
// ToXPCOMCallback already did the right QI for us.
|
||||
return supp.forget().downcast<XPCOMCallbackT>();
|
||||
}
|
||||
return nullptr;
|
||||
// ToXPCOMCallback already did the right QI for us.
|
||||
return supp.forget().downcast<XPCOMCallbackT>();
|
||||
}
|
||||
|
||||
// Try to return a WebIDLCallbackT version of this object.
|
||||
@@ -565,9 +530,7 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
if (aField) {
|
||||
CycleCollectionNoteChild(aCallback, aField.GetISupports(), aName, aFlags);
|
||||
}
|
||||
CycleCollectionNoteChild(aCallback, aField.GetISupports(), aName, aFlags);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
@@ -604,15 +567,10 @@ public:
|
||||
this->get().operator=(arg);
|
||||
}
|
||||
|
||||
// Codegen relies on being able to do CallbackOrNull() and Callback() on us.
|
||||
JS::Handle<JSObject*> CallbackOrNull() const
|
||||
// Codegen relies on being able to do Callback() on us.
|
||||
JS::Handle<JSObject*> Callback() const
|
||||
{
|
||||
return this->get()->CallbackOrNull();
|
||||
}
|
||||
|
||||
JSObject* Callback(JSContext* aCx) const
|
||||
{
|
||||
return this->get()->Callback(aCx);
|
||||
return this->get()->Callback();
|
||||
}
|
||||
|
||||
~RootedCallback()
|
||||
|
||||
+36
-105
@@ -449,9 +449,6 @@ class CGDOMJSClass(CGThing):
|
||||
traceHook = 'nullptr'
|
||||
reservedSlots = slotCount
|
||||
if self.descriptor.interface.isProbablyShortLivingObject():
|
||||
if not self.descriptor.wrapperCache:
|
||||
raise TypeError("Need a wrapper cache to support nursery "
|
||||
"allocation of DOM objects")
|
||||
classFlags += " | JSCLASS_SKIP_NURSERY_FINALIZE"
|
||||
if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
|
||||
resolveHook = RESOLVE_HOOK_NAME
|
||||
@@ -531,9 +528,7 @@ class CGDOMProxyJSClass(CGThing):
|
||||
return ""
|
||||
|
||||
def define(self):
|
||||
# We need one reserved slot (DOM_OBJECT_SLOT).
|
||||
flags = ["JSCLASS_IS_DOMJSCLASS",
|
||||
"JSCLASS_HAS_RESERVED_SLOTS(1)"]
|
||||
flags = ["JSCLASS_IS_DOMJSCLASS"]
|
||||
# We don't use an IDL annotation for JSCLASS_EMULATES_UNDEFINED because
|
||||
# we don't want people ever adding that to any interface other than
|
||||
# HTMLAllCollection. So just hardcode it here.
|
||||
@@ -1676,14 +1671,14 @@ class CGAddPropertyHook(CGAbstractClassHook):
|
||||
""")
|
||||
|
||||
|
||||
def finalizeHook(descriptor, hookName, freeOp, obj):
|
||||
def finalizeHook(descriptor, hookName, freeOp):
|
||||
finalize = ""
|
||||
if descriptor.wrapperCache:
|
||||
finalize += "ClearWrapper(self, self, %s);\n" % obj
|
||||
finalize += "ClearWrapper(self, self);\n"
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
finalize += "self->mExpandoAndGeneration.expando = JS::UndefinedValue();\n"
|
||||
if descriptor.isGlobal():
|
||||
finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), %s);\n" % (freeOp, obj)
|
||||
finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), obj);\n" % freeOp
|
||||
finalize += ("AddForDeferredFinalization<%s>(self);\n" %
|
||||
descriptor.nativeType)
|
||||
return CGIfWrapper(CGGeneric(finalize), "self")
|
||||
@@ -1699,8 +1694,7 @@ class CGClassFinalizeHook(CGAbstractClassHook):
|
||||
'void', args)
|
||||
|
||||
def generate_code(self):
|
||||
return finalizeHook(self.descriptor, self.name,
|
||||
self.args[0].name, self.args[1].name).define()
|
||||
return finalizeHook(self.descriptor, self.name, self.args[0].name).define()
|
||||
|
||||
|
||||
class CGClassObjectMovedHook(CGAbstractClassHook):
|
||||
@@ -3231,7 +3225,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
||||
*/
|
||||
|
||||
const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(${id});
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
|
||||
MOZ_ASSERT_IF(entrySlot, !JS::ObjectIsMarkedGray(entrySlot));
|
||||
return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
|
||||
""",
|
||||
id=self.id)
|
||||
@@ -3477,21 +3471,21 @@ def CreateBindingJSObject(descriptor, properties):
|
||||
# We don't always need to root obj, but there are a variety
|
||||
# of cases where we do, so for simplicity, just always root it.
|
||||
if descriptor.proxy:
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
expandoValue = "JS::PrivateValue(&aObject->mExpandoAndGeneration)"
|
||||
else:
|
||||
expandoValue = "JS::UndefinedValue()"
|
||||
create = fill(
|
||||
create = dedent(
|
||||
"""
|
||||
JS::Rooted<JS::Value> expandoValue(aCx, ${expandoValue});
|
||||
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
|
||||
proto, aObject, expandoValue, aReflector);
|
||||
proto, aObject, aReflector);
|
||||
if (!aReflector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
""",
|
||||
expandoValue=expandoValue)
|
||||
""")
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
create += dedent("""
|
||||
js::SetProxyExtra(aReflector, JSPROXYSLOT_EXPANDO,
|
||||
JS::PrivateValue(&aObject->mExpandoAndGeneration));
|
||||
|
||||
""")
|
||||
else:
|
||||
create = dedent(
|
||||
"""
|
||||
@@ -3736,7 +3730,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(JS_IsGlobalObject(global));
|
||||
MOZ_ASSERT(JS::ObjectIsNotGray(global));
|
||||
MOZ_ASSERT(!JS::ObjectIsMarkedGray(global));
|
||||
|
||||
// That might have ended up wrapping us already, due to the wonders
|
||||
// of XBL. Check for that, and bail out as needed.
|
||||
@@ -3952,15 +3946,11 @@ class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
||||
body += fill(
|
||||
"""
|
||||
|
||||
static_assert(${slot} < js::shadow::Object::MAX_FIXED_SLOTS,
|
||||
"Not enough fixed slots to fit '${interface}.${member}. Ion's visitGetDOMMemberV/visitGetDOMMemberT assume StoreInSlot things are all in fixed slots.");
|
||||
if (!get_${member}(aCx, aWrapper, aObject, args)) {
|
||||
return false;
|
||||
}
|
||||
// Getter handled setting our reserved slots
|
||||
""",
|
||||
slot=memberReservedSlot(m, self.descriptor),
|
||||
interface=self.descriptor.interface.identifier.name,
|
||||
member=m.identifier.name)
|
||||
|
||||
body += "\nreturn true;\n"
|
||||
@@ -4262,9 +4252,7 @@ class CastableObjectUnwrapper():
|
||||
// that already has a content reflection...
|
||||
if (!IsDOMObject(js::UncheckedUnwrap(&${source}.toObject()))) {
|
||||
nsCOMPtr<nsIGlobalObject> contentGlobal;
|
||||
JS::Handle<JSObject*> callback = CallbackOrNull();
|
||||
if (!callback ||
|
||||
!GetContentGlobalForJSImplementedObject(cx, callback, getter_AddRefs(contentGlobal))) {
|
||||
if (!GetContentGlobalForJSImplementedObject(cx, Callback(), getter_AddRefs(contentGlobal))) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
JS::Rooted<JSObject*> jsImplSourceObj(cx, &${source}.toObject());
|
||||
@@ -4936,7 +4924,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
}
|
||||
|
||||
${typeName}::EntryType* entry;
|
||||
if (!idsSeen.EnsureInserted(propName)) {
|
||||
if (idsSeen.Contains(propName)) {
|
||||
// Find the existing entry.
|
||||
auto idx = recordEntries.IndexOf(propName);
|
||||
MOZ_ASSERT(idx != recordEntries.NoIndex,
|
||||
@@ -4952,6 +4940,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
// Safe to do an infallible append here, because we did a
|
||||
// SetCapacity above to the right capacity.
|
||||
entry = recordEntries.AppendElement();
|
||||
idsSeen.PutEntry(propName);
|
||||
}
|
||||
entry->mKey = propName;
|
||||
${valueType}& slot = entry->mValue;
|
||||
@@ -6739,10 +6728,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||
return conversion, False
|
||||
|
||||
if type.isCallback() or type.isCallbackInterface():
|
||||
# Callbacks can store null if we nuked the compartments their
|
||||
# objects lived in.
|
||||
wrapCode = setObjectOrNull(
|
||||
"GetCallbackFromCallbackObject(cx, %(result)s)",
|
||||
wrapCode = setObject(
|
||||
"*GetCallbackFromCallbackObject(%(result)s)",
|
||||
wrapAsType=type)
|
||||
if type.nullable():
|
||||
wrapCode = (
|
||||
@@ -7192,8 +7179,7 @@ class CGCallGenerator(CGThing):
|
||||
if needsCallerType:
|
||||
args.append(CGGeneric("callerType"))
|
||||
|
||||
canOOM = "canOOM" in extendedAttributes
|
||||
if isFallible or canOOM:
|
||||
if isFallible:
|
||||
args.append(CGGeneric("rv"))
|
||||
args.extend(CGGeneric(arg) for arg in argsPost)
|
||||
|
||||
@@ -7277,12 +7263,8 @@ class CGCallGenerator(CGThing):
|
||||
self.cgRoot.prepend(callerCheck)
|
||||
self.cgRoot.prepend(CGGeneric("CallerType callerType;\n"))
|
||||
|
||||
if isFallible or canOOM:
|
||||
if isFallible:
|
||||
reporterClass = "binding_detail::FastErrorResult"
|
||||
else:
|
||||
reporterClass = "binding_danger::OOMReporterInstantiator"
|
||||
self.cgRoot.prepend(CGGeneric("%s rv;\n" % reporterClass))
|
||||
if isFallible:
|
||||
self.cgRoot.prepend(CGGeneric("binding_detail::FastErrorResult rv;\n"))
|
||||
self.cgRoot.append(CGGeneric(dedent(
|
||||
"""
|
||||
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
|
||||
@@ -9061,10 +9043,9 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
|
||||
nativeName = MakeNativeName(descriptor.binaryNameFor(name))
|
||||
_, resultOutParam, _, _, _ = getRetvalDeclarationForType(attr.type,
|
||||
descriptor)
|
||||
extendedAttrs = descriptor.getExtendedAttributes(attr, getter=True)
|
||||
canFail = ('infallible' not in extendedAttrs or
|
||||
'canOOM' in extendedAttrs)
|
||||
if resultOutParam or attr.type.nullable() or canFail:
|
||||
infallible = ('infallible' in
|
||||
descriptor.getExtendedAttributes(attr, getter=True))
|
||||
if resultOutParam or attr.type.nullable() or not infallible:
|
||||
nativeName = "Get" + nativeName
|
||||
return nativeName
|
||||
|
||||
@@ -9362,27 +9343,13 @@ class CGMemberJITInfo(CGThing):
|
||||
# while we have the right type.
|
||||
getter = ("(JSJitGetterOp)get_%s" %
|
||||
IDLToCIdentifier(self.member.identifier.name))
|
||||
extendedAttrs = self.descriptor.getExtendedAttributes(self.member, getter=True)
|
||||
getterinfal = "infallible" in extendedAttrs
|
||||
|
||||
# At this point getterinfal is true if our getter either can't throw
|
||||
# at all, or can only throw OOM. In both cases, it's safe to move,
|
||||
# or dead-code-eliminate, the getter, because throwing OOM is not
|
||||
# semantically meaningful, so code can't rely on it happening. Note
|
||||
# that this makes the behavior consistent for OOM thrown from the
|
||||
# getter itself and OOM thrown from the to-JS conversion of the
|
||||
# return value (see the "canOOM" and "infallibleForMember" checks
|
||||
# below).
|
||||
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
|
||||
|
||||
movable = self.mayBeMovable() and getterinfal
|
||||
eliminatable = self.mayBeEliminatable() and getterinfal
|
||||
aliasSet = self.aliasSet()
|
||||
|
||||
# Now we have to set getterinfal to whether we can _really_ ever
|
||||
# throw, from the point of view of the JS engine.
|
||||
getterinfal = (getterinfal and
|
||||
"canOOM" not in extendedAttrs and
|
||||
infallibleForMember(self.member, self.member.type, self.descriptor))
|
||||
getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
|
||||
isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
|
||||
if self.member.slotIndices is not None:
|
||||
assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
|
||||
@@ -9445,16 +9412,7 @@ class CGMemberJITInfo(CGThing):
|
||||
# argument conversions, since argument conversions that can
|
||||
# reliably throw would be effectful anyway and the jit doesn't
|
||||
# move effectful things.
|
||||
extendedAttrs = self.descriptor.getExtendedAttributes(self.member)
|
||||
hasInfallibleImpl = "infallible" in extendedAttrs
|
||||
# At this point hasInfallibleImpl is true if our method either
|
||||
# can't throw at all, or can only throw OOM. In both cases, it
|
||||
# may be safe to move, or dead-code-eliminate, the method,
|
||||
# because throwing OOM is not semantically meaningful, so code
|
||||
# can't rely on it happening. Note that this makes the behavior
|
||||
# consistent for OOM thrown from the method itself and OOM
|
||||
# thrown from the to-JS conversion of the return value (see the
|
||||
# "canOOM" and "infallibleForMember" checks below).
|
||||
hasInfallibleImpl = "infallible" in self.descriptor.getExtendedAttributes(self.member)
|
||||
movable = self.mayBeMovable() and hasInfallibleImpl
|
||||
eliminatable = self.mayBeEliminatable() and hasInfallibleImpl
|
||||
# XXXbz can we move the smarts about fallibility due to arg
|
||||
@@ -9464,8 +9422,7 @@ class CGMemberJITInfo(CGThing):
|
||||
# We have arguments or our return-value boxing can fail
|
||||
methodInfal = False
|
||||
else:
|
||||
methodInfal = (hasInfallibleImpl and
|
||||
"canOOM" not in extendedAttrs)
|
||||
methodInfal = hasInfallibleImpl
|
||||
# For now, only bother to output args if we're side-effect-free.
|
||||
if self.member.affects == "Nothing":
|
||||
args = sig[1]
|
||||
@@ -10973,7 +10930,6 @@ class CGResolveOwnPropertyViaResolve(CGAbstractBindingMethod):
|
||||
// to avoid re-resolving the properties if someone deletes
|
||||
// them.
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
JS_MarkCrossZoneId(cx, id);
|
||||
JS::Rooted<JS::PropertyDescriptor> objDesc(cx);
|
||||
if (!self->DoResolve(cx, obj, id, &objDesc)) {
|
||||
return false;
|
||||
@@ -11395,7 +11351,7 @@ class CGProxyUnwrap(CGAbstractMethod):
|
||||
obj = js::UncheckedUnwrap(obj);
|
||||
}
|
||||
MOZ_ASSERT(IsProxy(obj));
|
||||
return static_cast<${type}*>(js::GetProxyReservedSlot(obj, DOM_OBJECT_SLOT).toPrivate());
|
||||
return static_cast<${type}*>(js::GetProxyPrivate(obj).toPrivate());
|
||||
""",
|
||||
type=self.descriptor.nativeType)
|
||||
|
||||
@@ -12103,8 +12059,7 @@ class CGDOMJSProxyHandler_finalize(ClassMethod):
|
||||
def getBody(self):
|
||||
return (("%s* self = UnwrapPossiblyNotInitializedDOMObject<%s>(proxy);\n" %
|
||||
(self.descriptor.nativeType, self.descriptor.nativeType)) +
|
||||
finalizeHook(self.descriptor, FINALIZE_HOOK_NAME,
|
||||
self.args[0].name, self.args[1].name).define())
|
||||
finalizeHook(self.descriptor, FINALIZE_HOOK_NAME, self.args[0].name).define())
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_getElements(ClassMethod):
|
||||
@@ -12218,21 +12173,6 @@ class CGDOMJSProxyHandler_isCallable(ClassMethod):
|
||||
return true;
|
||||
""")
|
||||
|
||||
class CGDOMJSProxyHandler_canNurseryAllocate(ClassMethod):
|
||||
"""
|
||||
Override the default canNurseryAllocate in BaseProxyHandler, for cases when
|
||||
we should be nursery-allocated.
|
||||
"""
|
||||
def __init__(self):
|
||||
ClassMethod.__init__(self, "canNurseryAllocate", "bool",
|
||||
[],
|
||||
virtual=True, override=True, const=True)
|
||||
|
||||
def getBody(self):
|
||||
return dedent("""
|
||||
return true;
|
||||
""")
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler(CGClass):
|
||||
def __init__(self, descriptor):
|
||||
@@ -12270,11 +12210,6 @@ class CGDOMJSProxyHandler(CGClass):
|
||||
if descriptor.operations['LegacyCaller']:
|
||||
methods.append(CGDOMJSProxyHandler_call())
|
||||
methods.append(CGDOMJSProxyHandler_isCallable())
|
||||
if descriptor.interface.isProbablyShortLivingObject():
|
||||
if not descriptor.wrapperCache:
|
||||
raise TypeError("Need a wrapper cache to support nursery "
|
||||
"allocation of DOM objects")
|
||||
methods.append(CGDOMJSProxyHandler_canNurseryAllocate())
|
||||
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
parentClass = 'ShadowingDOMProxyHandler'
|
||||
@@ -14355,12 +14290,10 @@ class CGNativeMember(ClassMethod):
|
||||
# And the caller type, if desired.
|
||||
if needsCallerType(self.member):
|
||||
args.append(Argument("CallerType", "aCallerType"))
|
||||
# And the ErrorResult or OOMReporter
|
||||
# And the ErrorResult
|
||||
if 'infallible' not in self.extendedAttrs:
|
||||
# Use aRv so it won't conflict with local vars named "rv"
|
||||
args.append(Argument("ErrorResult&", "aRv"))
|
||||
elif 'canOOM' in self.extendedAttrs:
|
||||
args.append(Argument("OOMReporter&", "aRv"))
|
||||
# The legacycaller thisval
|
||||
if self.member.isMethod() and self.member.isLegacycaller():
|
||||
# If it has an identifier, we can't deal with it yet
|
||||
@@ -15275,11 +15208,11 @@ class CGJSImplClass(CGBindingImplClass):
|
||||
}
|
||||
|
||||
// Now define it on our chrome object
|
||||
JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
|
||||
JSAutoCompartment ac(aCx, mImpl->Callback());
|
||||
if (!JS_WrapObject(aCx, &obj)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
|
||||
if (!JS_DefineProperty(aCx, mImpl->Callback(), "__DOM_IMPL__", obj, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
return obj;
|
||||
@@ -17073,8 +17006,6 @@ class CGEventGetter(CGNativeMember):
|
||||
def getArgs(self, returnType, argList):
|
||||
if 'infallible' not in self.extendedAttrs:
|
||||
raise TypeError("Event code generator does not support [Throws]!")
|
||||
if 'canOOM' in self.extendedAttrs:
|
||||
raise TypeError("Event code generator does not support [CanOOM]!")
|
||||
if not self.member.isAttr():
|
||||
raise TypeError("Event code generator does not support methods")
|
||||
if self.member.isStatic():
|
||||
|
||||
@@ -568,29 +568,17 @@ class Descriptor(DescriptorProvider):
|
||||
return self.isGlobal() and self.supportsNamedProperties()
|
||||
|
||||
def getExtendedAttributes(self, member, getter=False, setter=False):
|
||||
def ensureValidBoolExtendedAttribute(attr, name):
|
||||
if (attr is not None and attr is not True):
|
||||
raise TypeError("Unknown value for '%s': %s" % (name, attr[0]))
|
||||
|
||||
def ensureValidThrowsExtendedAttribute(attr):
|
||||
ensureValidBoolExtendedAttribute(attr, "Throws")
|
||||
|
||||
def ensureValidCanOOMExtendedAttribute(attr):
|
||||
ensureValidBoolExtendedAttribute(attr, "CanOOM")
|
||||
if (attr is not None and attr is not True):
|
||||
raise TypeError("Unknown value for 'Throws': " + attr[0])
|
||||
|
||||
def maybeAppendInfallibleToAttrs(attrs, throws):
|
||||
ensureValidThrowsExtendedAttribute(throws)
|
||||
if throws is None:
|
||||
attrs.append("infallible")
|
||||
|
||||
def maybeAppendCanOOMToAttrs(attrs, canOOM):
|
||||
ensureValidCanOOMExtendedAttribute(canOOM)
|
||||
if canOOM is not None:
|
||||
attrs.append("canOOM")
|
||||
|
||||
name = member.identifier.name
|
||||
throws = self.interface.isJSImplemented() or member.getExtendedAttribute("Throws")
|
||||
canOOM = member.getExtendedAttribute("CanOOM")
|
||||
if member.isMethod():
|
||||
# JSObject-returning [NewObject] methods must be fallible,
|
||||
# since they have to (fallibly) allocate the new JSObject.
|
||||
@@ -599,7 +587,6 @@ class Descriptor(DescriptorProvider):
|
||||
throws = True
|
||||
attrs = self.extendedAttributes['all'].get(name, [])
|
||||
maybeAppendInfallibleToAttrs(attrs, throws)
|
||||
maybeAppendCanOOMToAttrs(attrs, canOOM)
|
||||
return attrs
|
||||
|
||||
assert member.isAttr()
|
||||
@@ -610,10 +597,6 @@ class Descriptor(DescriptorProvider):
|
||||
throwsAttr = "GetterThrows" if getter else "SetterThrows"
|
||||
throws = member.getExtendedAttribute(throwsAttr)
|
||||
maybeAppendInfallibleToAttrs(attrs, throws)
|
||||
if canOOM is None:
|
||||
canOOMAttr = "GetterCanOOM" if getter else "SetterCanOOM"
|
||||
canOOM = member.getExtendedAttribute(canOOMAttr)
|
||||
maybeAppendCanOOMToAttrs(attrs, canOOM)
|
||||
return attrs
|
||||
|
||||
def supportsIndexedProperties(self):
|
||||
|
||||
@@ -33,7 +33,7 @@ js::DOMProxyShadowsResult
|
||||
DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
|
||||
{
|
||||
JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
|
||||
JS::Value v = js::GetProxyPrivate(proxy);
|
||||
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
|
||||
bool isOverrideBuiltins = !v.isObject() && !v.isUndefined();
|
||||
if (expando) {
|
||||
bool hasOwn;
|
||||
@@ -63,26 +63,24 @@ struct SetDOMProxyInformation
|
||||
{
|
||||
SetDOMProxyInformation() {
|
||||
js::SetDOMProxyInformation((const void*) &DOMProxyHandler::family,
|
||||
DOMProxyShadows);
|
||||
JSPROXYSLOT_EXPANDO, DOMProxyShadows);
|
||||
}
|
||||
};
|
||||
|
||||
SetDOMProxyInformation gSetDOMProxyInformation;
|
||||
|
||||
|
||||
// static
|
||||
JSObject*
|
||||
DOMProxyHandler::GetAndClearExpandoObject(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
if (v.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (v.isObject()) {
|
||||
js::SetProxyPrivate(obj, UndefinedValue());
|
||||
|
||||
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue());
|
||||
} else {
|
||||
js::ExpandoAndGeneration* expandoAndGeneration =
|
||||
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
||||
@@ -115,7 +113,7 @@ JSObject*
|
||||
DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
{
|
||||
NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
if (v.isObject()) {
|
||||
return &v.toObject();
|
||||
}
|
||||
@@ -150,7 +148,7 @@ DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
return expando;
|
||||
}
|
||||
|
||||
js::SetProxyPrivate(obj, ObjectValue(*expando));
|
||||
js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
|
||||
|
||||
return expando;
|
||||
}
|
||||
@@ -281,7 +279,7 @@ JSObject *
|
||||
DOMProxyHandler::GetExpandoObject(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyPrivate(obj);
|
||||
JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
if (v.isObject()) {
|
||||
return &v.toObject();
|
||||
}
|
||||
@@ -302,12 +300,14 @@ ShadowingDOMProxyHandler::trace(JSTracer* trc, JSObject* proxy) const
|
||||
DOMProxyHandler::trace(trc, proxy);
|
||||
|
||||
MOZ_ASSERT(IsDOMProxy(proxy), "expected a DOM proxy object");
|
||||
JS::Value v = js::GetProxyPrivate(proxy);
|
||||
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
|
||||
MOZ_ASSERT(!v.isObject(), "Should not have expando object directly!");
|
||||
|
||||
// The proxy's private slot is set when we allocate the proxy,
|
||||
// so it cannot be |undefined|.
|
||||
MOZ_ASSERT(!v.isUndefined());
|
||||
if (v.isUndefined()) {
|
||||
// This can happen if we GC while creating our object, before we get a
|
||||
// chance to set up its JSPROXYSLOT_EXPANDO slot.
|
||||
return;
|
||||
}
|
||||
|
||||
js::ExpandoAndGeneration* expandoAndGeneration =
|
||||
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
|
||||
|
||||
@@ -13,29 +13,35 @@
|
||||
#include "js/Proxy.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* DOM proxies store the expando object in the private slot.
|
||||
*
|
||||
* The expando object is a plain JSObject whose properties correspond to
|
||||
* "expandos" (custom properties set by the script author).
|
||||
*
|
||||
* The exact value stored in the proxy's private slot depends on whether the
|
||||
* interface is annotated with the [OverrideBuiltins] extended attribute.
|
||||
*
|
||||
* If it is, the proxy is initialized with a PrivateValue, which contains a
|
||||
* pointer to a js::ExpandoAndGeneration object; this contains a pointer to
|
||||
* the actual expando object as well as the "generation" of the object. The
|
||||
* proxy handler will trace the expando object stored in the
|
||||
* js::ExpandoAndGeneration while the proxy itself is alive.
|
||||
*
|
||||
* If it is not, the proxy is initialized with an UndefinedValue. In
|
||||
* EnsureExpandoObject, it is set to an ObjectValue that points to the
|
||||
* expando object directly. (It is set back to an UndefinedValue only when
|
||||
* the object is about to die.)
|
||||
*/
|
||||
enum {
|
||||
/**
|
||||
* DOM proxies have an extra slot for the expando object at index
|
||||
* JSPROXYSLOT_EXPANDO.
|
||||
*
|
||||
* The expando object is a plain JSObject whose properties correspond to
|
||||
* "expandos" (custom properties set by the script author).
|
||||
*
|
||||
* The exact value stored in the JSPROXYSLOT_EXPANDO slot depends on whether
|
||||
* the interface is annotated with the [OverrideBuiltins] extended attribute.
|
||||
*
|
||||
* If it is, the proxy is initialized with a PrivateValue, which contains a
|
||||
* pointer to a js::ExpandoAndGeneration object; this contains a pointer to
|
||||
* the actual expando object as well as the "generation" of the object. The
|
||||
* proxy handler will trace the expando object stored in the
|
||||
* js::ExpandoAndGeneration while the proxy itself is alive.
|
||||
*
|
||||
* If it is not, the proxy is initialized with an UndefinedValue. In
|
||||
* EnsureExpandoObject, it is set to an ObjectValue that points to the
|
||||
* expando object directly. (It is set back to an UndefinedValue only when
|
||||
* the object is about to die.)
|
||||
*/
|
||||
JSPROXYSLOT_EXPANDO = 0
|
||||
};
|
||||
|
||||
template<typename T> struct Prefable;
|
||||
|
||||
|
||||
@@ -101,7 +101,6 @@ struct StringArrayAppender
|
||||
} // namespace dom
|
||||
|
||||
class ErrorResult;
|
||||
class OOMReporter;
|
||||
|
||||
namespace binding_danger {
|
||||
|
||||
@@ -162,7 +161,6 @@ public:
|
||||
}
|
||||
|
||||
operator ErrorResult&();
|
||||
operator OOMReporter&();
|
||||
|
||||
void Throw(nsresult rv) {
|
||||
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
|
||||
@@ -557,82 +555,6 @@ class IgnoredErrorResult :
|
||||
{
|
||||
};
|
||||
|
||||
namespace dom {
|
||||
namespace binding_detail {
|
||||
class FastErrorResult :
|
||||
public mozilla::binding_danger::TErrorResult<
|
||||
mozilla::binding_danger::JustAssertCleanupPolicy>
|
||||
{
|
||||
};
|
||||
} // namespace binding_detail
|
||||
} // namespace dom
|
||||
|
||||
// This part is a bit annoying. We want an OOMReporter class that has the
|
||||
// following properties:
|
||||
//
|
||||
// 1) Can be cast to from any ErrorResult-like type.
|
||||
// 2) Has a fast destructor (because we want to use it from bindings).
|
||||
// 3) Won't be randomly instantiated by non-binding code (because the fast
|
||||
// destructor is not so safe.
|
||||
// 4) Doesn't look ugly on the callee side (e.g. isn't in the binding_detail or
|
||||
// binding_danger namespace).
|
||||
//
|
||||
// We do this by having two classes: The class callees should use, which has the
|
||||
// things we want and a private constructor, and a friend subclass in the
|
||||
// binding_danger namespace that can be used to construct it.
|
||||
namespace binding_danger {
|
||||
class OOMReporterInstantiator;
|
||||
} // namespace binding_danger
|
||||
|
||||
class OOMReporter : private dom::binding_detail::FastErrorResult
|
||||
{
|
||||
public:
|
||||
void ReportOOM()
|
||||
{
|
||||
Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
private:
|
||||
// OOMReporterInstantiator is a friend so it can call our constructor and
|
||||
// MaybeSetPendingException.
|
||||
friend class binding_danger::OOMReporterInstantiator;
|
||||
|
||||
// TErrorResult is a friend so its |operator OOMReporter&()| can work.
|
||||
template<typename CleanupPolicy>
|
||||
friend class binding_danger::TErrorResult;
|
||||
|
||||
OOMReporter()
|
||||
: dom::binding_detail::FastErrorResult()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace binding_danger {
|
||||
class OOMReporterInstantiator : public OOMReporter
|
||||
{
|
||||
public:
|
||||
OOMReporterInstantiator()
|
||||
: OOMReporter()
|
||||
{
|
||||
}
|
||||
|
||||
// We want to be able to call MaybeSetPendingException from codegen. The one
|
||||
// on OOMReporter is not callable directly, because it comes from a private
|
||||
// superclass. But we're a friend, so _we_ can call it.
|
||||
bool MaybeSetPendingException(JSContext* cx)
|
||||
{
|
||||
return OOMReporter::MaybeSetPendingException(cx);
|
||||
}
|
||||
};
|
||||
} // namespace binding_danger
|
||||
|
||||
template<typename CleanupPolicy>
|
||||
binding_danger::TErrorResult<CleanupPolicy>::operator OOMReporter&()
|
||||
{
|
||||
return *static_cast<OOMReporter*>(
|
||||
reinterpret_cast<TErrorResult<JustAssertCleanupPolicy>*>(this));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** Macros for checking results
|
||||
******************************************************************************/
|
||||
|
||||
@@ -111,3 +111,4 @@ MSG_DEF(MSG_PMO_INVALID_MEMBERS, 0, JSEXN_TYPEERR, "PerformanceMeasureOptions ca
|
||||
MSG_DEF(MSG_PMO_CONSTRUCTOR_INACCESSIBLE, 0, JSEXN_TYPEERR, "Can't access PerformanceMark constructor, performance is null.")
|
||||
MSG_DEF(MSG_PMO_UNEXPECTED_START_TIME, 0, JSEXN_TYPEERR, "Expected startTime >= 0.")
|
||||
MSG_DEF(MSG_PMO_INVALID_ATTR_FOR_NON_GLOBAL, 1, JSEXN_TYPEERR, "Cannot get PerformanceTiming attribute values for non-Window global object. Given: {0}.")
|
||||
MSG_DEF(MSG_NOT_SUBMIT_BUTTON, 0, JSEXN_TYPEERR, "The submitter is not a submit button.")
|
||||
@@ -46,7 +46,6 @@ SimpleGlobal_finalize(js::FreeOp *fop, JSObject *obj)
|
||||
{
|
||||
SimpleGlobalObject* globalObject =
|
||||
static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
|
||||
globalObject->ClearWrapper(obj);
|
||||
NS_RELEASE(globalObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
|
||||
virtual ~SimpleGlobalObject()
|
||||
{
|
||||
MOZ_ASSERT(!GetWrapperMaybeDead());
|
||||
ClearWrapper();
|
||||
}
|
||||
|
||||
const GlobalType mType;
|
||||
|
||||
@@ -131,7 +131,7 @@ ToJSValue(JSContext* aCx,
|
||||
// Make sure we're called in a compartment
|
||||
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
|
||||
|
||||
aValue.setObjectOrNull(aArgument.Callback(aCx));
|
||||
aValue.setObject(*aArgument.Callback());
|
||||
|
||||
return MaybeWrapValue(aCx, aValue);
|
||||
}
|
||||
|
||||
@@ -4116,19 +4116,15 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
|
||||
def handleExtendedAttribute(self, attr):
|
||||
identifier = attr.identifier()
|
||||
if ((identifier == "SetterThrows" or identifier == "SetterCanOOM")
|
||||
and self.readonly):
|
||||
if identifier == "SetterThrows" and self.readonly:
|
||||
raise WebIDLError("Readonly attributes must not be flagged as "
|
||||
"[%s]" % identifier,
|
||||
"[SetterThrows]",
|
||||
[self.location])
|
||||
elif (((identifier == "Throws" or identifier == "GetterThrows" or
|
||||
identifier == "CanOOM" or identifier == "GetterCanOOM") and
|
||||
elif (((identifier == "Throws" or identifier == "GetterThrows") and
|
||||
self.getExtendedAttribute("StoreInSlot")) or
|
||||
(identifier == "StoreInSlot" and
|
||||
(self.getExtendedAttribute("Throws") or
|
||||
self.getExtendedAttribute("GetterThrows") or
|
||||
self.getExtendedAttribute("CanOOM") or
|
||||
self.getExtendedAttribute("GetterCanOOM")))):
|
||||
self.getExtendedAttribute("GetterThrows")))):
|
||||
raise WebIDLError("Throwing things can't be [StoreInSlot]",
|
||||
[attr.location])
|
||||
elif identifier == "LenientThis":
|
||||
@@ -4291,9 +4287,6 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
identifier == "SetterThrows" or
|
||||
identifier == "Throws" or
|
||||
identifier == "GetterThrows" or
|
||||
identifier == "SetterCanOOM" or
|
||||
identifier == "CanOOM" or
|
||||
identifier == "GetterCanOOM" or
|
||||
identifier == "ChromeOnly" or
|
||||
identifier == "Func" or
|
||||
identifier == "SecureContext" or
|
||||
@@ -4951,12 +4944,13 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
|
||||
def handleExtendedAttribute(self, attr):
|
||||
identifier = attr.identifier()
|
||||
if (identifier == "GetterThrows" or
|
||||
identifier == "SetterThrows" or
|
||||
identifier == "GetterCanOOM" or
|
||||
identifier == "SetterCanOOM"):
|
||||
if identifier == "GetterThrows":
|
||||
raise WebIDLError("Methods must not be flagged as "
|
||||
"[%s]" % identifier,
|
||||
"[GetterThrows]",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "SetterThrows":
|
||||
raise WebIDLError("Methods must not be flagged as "
|
||||
"[SetterThrows]",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "Unforgeable":
|
||||
if self.isStatic():
|
||||
@@ -5029,7 +5023,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
"attribute, setter, and deleter",
|
||||
[attr.location, self.location])
|
||||
elif (identifier == "Throws" or
|
||||
identifier == "CanOOM" or
|
||||
identifier == "NewObject" or
|
||||
identifier == "ChromeOnly" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "js/HeapAPI.h"
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
@@ -122,7 +121,6 @@
|
||||
#include "nsFontMetrics.h"
|
||||
#include "Units.h"
|
||||
#include "CanvasUtils.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "mozilla/layers/CanvasClient.h"
|
||||
|
||||
@@ -1749,12 +1747,6 @@ CanvasRenderingContext2D::RegisterAllocation()
|
||||
if (context) {
|
||||
JS_updateMallocCounter(context, mWidth * mHeight * 4);
|
||||
}
|
||||
|
||||
JSObject* wrapper = GetWrapperPreserveColor();
|
||||
if (wrapper) {
|
||||
CycleCollectedJSContext::Get()->
|
||||
AddZoneWaitingForGC(JS::GetObjectZone(wrapper));
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<LayerManager>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "WebGLActiveInfo.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
@@ -27,6 +28,30 @@ namespace mozilla {
|
||||
// For a Tegra workaround.
|
||||
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
|
||||
|
||||
static uint8_t
|
||||
NumUsedLocationsByElemTypeForDraw(GLenum elemType)
|
||||
{
|
||||
switch (elemType) {
|
||||
case LOCAL_GL_FLOAT_MAT2:
|
||||
case LOCAL_GL_FLOAT_MAT2x3:
|
||||
case LOCAL_GL_FLOAT_MAT2x4:
|
||||
return 2;
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT3x2:
|
||||
case LOCAL_GL_FLOAT_MAT3:
|
||||
case LOCAL_GL_FLOAT_MAT3x4:
|
||||
return 3;
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT4x2:
|
||||
case LOCAL_GL_FLOAT_MAT4x3:
|
||||
case LOCAL_GL_FLOAT_MAT4:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
class ScopedResolveTexturesForDraw
|
||||
@@ -331,6 +356,7 @@ class ScopedDrawHelper final
|
||||
{
|
||||
WebGLContext* const mWebGL;
|
||||
bool mDidFake;
|
||||
std::vector<GLuint> mDisabledUnusedAttribs;
|
||||
|
||||
public:
|
||||
ScopedDrawHelper(WebGLContext* webgl, const char* funcName, uint32_t firstVertex,
|
||||
@@ -367,11 +393,43 @@ public:
|
||||
}
|
||||
mDidFake = true;
|
||||
|
||||
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (mWebGL->gl->WorkAroundDriverBugs()) {
|
||||
std::vector<bool> isActiveAttrib(mWebGL->mBoundVertexArray->mAttribs.Length(),
|
||||
false);
|
||||
for (const auto& progAttrib : linkInfo->attribs) {
|
||||
const auto loc = progAttrib.mLoc;
|
||||
if (loc < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto usedLocs =
|
||||
NumUsedLocationsByElemTypeForDraw(progAttrib.mActiveInfo->mElemType);
|
||||
for (uint32_t i = 0; i < usedLocs; ++i) {
|
||||
const auto usedLoc = static_cast<uint32_t>(loc) + i;
|
||||
if (usedLoc < isActiveAttrib.size()) {
|
||||
isActiveAttrib[usedLoc] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mWebGL->mBoundVertexArray->mAttribs.Length(); ++i) {
|
||||
const auto& attrib = mWebGL->mBoundVertexArray->mAttribs[i];
|
||||
if (!attrib.mEnabled || isActiveAttrib[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mWebGL->gl->fDisableVertexAttribArray(i);
|
||||
mDisabledUnusedAttribs.push_back(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
////
|
||||
// Check UBO sizes.
|
||||
|
||||
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
|
||||
|
||||
for (const auto& cur : linkInfo->uniformBlocks) {
|
||||
const auto& dataSize = cur->mDataSize;
|
||||
const auto& binding = cur->mBinding;
|
||||
@@ -477,6 +535,10 @@ public:
|
||||
if (mDidFake) {
|
||||
mWebGL->UndoFakeVertexAttrib0();
|
||||
}
|
||||
|
||||
for (const auto loc : mDisabledUnusedAttribs) {
|
||||
mWebGL->gl->fEnableVertexAttribArray(loc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -607,12 +669,12 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
@@ -855,12 +917,12 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
|
||||
@@ -176,6 +176,8 @@ public:
|
||||
void
|
||||
Trace(const TraceCallbacks& aCallbacks, void* aClosure)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
ConsoleCallData* tmp = this;
|
||||
for (uint32_t i = 0; i < mCopiedArguments.Length(); ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCopiedArguments[i])
|
||||
@@ -2276,16 +2278,11 @@ Console::NotifyHandler(JSContext* aCx, const Sequence<JS::Value>& aArguments,
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
|
||||
JS::Rooted<JSObject*> callable(aCx, mConsoleEventNotifier->CallableOrNull());
|
||||
if (NS_WARN_IF(!callable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// aCx and aArguments are in the same compartment because this method is
|
||||
// called directly when a Console.something() runs.
|
||||
// mConsoleEventNotifier->Callable() is the scope where value will be sent to.
|
||||
if (NS_WARN_IF(!PopulateConsoleNotificationInTheTargetScope(aCx, aArguments,
|
||||
callable,
|
||||
mConsoleEventNotifier->Callable(),
|
||||
&value,
|
||||
aCallData))) {
|
||||
return;
|
||||
|
||||
@@ -322,7 +322,7 @@ DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
|
||||
{
|
||||
EventHandlerNonNull* handler = GetEventHandler(aType, EmptyString());
|
||||
if (handler) {
|
||||
*aValue = JS::ObjectValue(*handler->Callback(aCx));
|
||||
*aValue = JS::ObjectValue(*handler->Callable());
|
||||
} else {
|
||||
*aValue = JS::NullValue();
|
||||
}
|
||||
|
||||
@@ -1533,16 +1533,10 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
|
||||
} else {
|
||||
eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2));
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventListener> callback = listener.mListener.ToXPCOMCallback();
|
||||
if (!callback) {
|
||||
// This will be null for cross-compartment event listeners which have been
|
||||
// destroyed.
|
||||
continue;
|
||||
}
|
||||
// EventListenerInfo is defined in XPCOM, so we have to go ahead
|
||||
// and convert to an XPCOM callback here...
|
||||
RefPtr<EventListenerInfo> info =
|
||||
new EventListenerInfo(eventType, callback.forget(),
|
||||
new EventListenerInfo(eventType, listener.mListener.ToXPCOMCallback(),
|
||||
listener.mFlags.mCapture,
|
||||
listener.mFlags.mAllowUntrustedEvents,
|
||||
listener.mFlags.mInSystemGroup);
|
||||
|
||||
@@ -137,7 +137,7 @@ EventListenerInfo::GetJSVal(JSContext* aCx,
|
||||
nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener);
|
||||
if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) {
|
||||
JS::Handle<JSObject*> handler =
|
||||
jsHandler->GetTypedEventHandler().Ptr()->CallableOrNull();
|
||||
jsHandler->GetTypedEventHandler().Ptr()->Callable();
|
||||
if (handler) {
|
||||
aAc.emplace(aCx, handler);
|
||||
aJSVal.setObject(*handler);
|
||||
@@ -376,13 +376,12 @@ EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarg
|
||||
&EventListenerService::NotifyPendingChanges));
|
||||
}
|
||||
|
||||
RefPtr<EventListenerChange> changes =
|
||||
mPendingListenerChangesSet.LookupForAdd(aTarget).OrInsert(
|
||||
[this, aTarget] () {
|
||||
EventListenerChange* c = new EventListenerChange(aTarget);
|
||||
mPendingListenerChanges->AppendElement(c, false);
|
||||
return c;
|
||||
});
|
||||
RefPtr<EventListenerChange> changes = mPendingListenerChangesSet.Get(aTarget);
|
||||
if (!changes) {
|
||||
changes = new EventListenerChange(aTarget);
|
||||
mPendingListenerChanges->AppendElement(changes, false);
|
||||
mPendingListenerChangesSet.Put(aTarget, changes);
|
||||
}
|
||||
changes->AddChangedListenerName(aName);
|
||||
}
|
||||
|
||||
|
||||
@@ -4366,8 +4366,13 @@ EventStateManager::GetWrapperByEventID(WidgetMouseEvent* aEvent)
|
||||
}
|
||||
return mMouseEnterLeaveHelper;
|
||||
}
|
||||
return mPointersEnterLeaveHelper.LookupForAdd(pointer->pointerId).OrInsert(
|
||||
[] () { return new OverOutElementsWrapper(); });
|
||||
RefPtr<OverOutElementsWrapper> helper;
|
||||
if (!mPointersEnterLeaveHelper.Get(pointer->pointerId, getter_AddRefs(helper))) {
|
||||
helper = new OverOutElementsWrapper();
|
||||
mPointersEnterLeaveHelper.Put(pointer->pointerId, helper);
|
||||
}
|
||||
|
||||
return helper;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
||||
@@ -884,10 +884,6 @@ IMEContentObserver::CharacterDataWillChange(nsIDocument* aDocument,
|
||||
{
|
||||
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||
"character data changed for non-text node");
|
||||
if (!aContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return; // Ignore if it's a comment node or something other invisible data
|
||||
// node.
|
||||
}
|
||||
MOZ_ASSERT(mPreCharacterDataChangeLength < 0,
|
||||
"CharacterDataChanged() should've reset "
|
||||
"mPreCharacterDataChangeLength");
|
||||
@@ -907,10 +903,6 @@ IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
CharacterDataChangeInfo* aInfo)
|
||||
{
|
||||
if (!aContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return; // Ignore if it's a comment node or something other invisible data
|
||||
// node.
|
||||
}
|
||||
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||
"character data changed for non-text node");
|
||||
|
||||
|
||||
@@ -772,21 +772,6 @@ GetFileHandleThreadPoolFor(FileHandleStorage aStorage)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult ClampResultCode(nsresult aResultCode) {
|
||||
if (NS_SUCCEEDED(aResultCode) ||
|
||||
NS_ERROR_GET_MODULE(aResultCode) == NS_ERROR_MODULE_DOM_FILEHANDLE) {
|
||||
return aResultCode;
|
||||
}
|
||||
|
||||
NS_WARNING(nsPrintfCString("Converting non-filehandle error code (0x%" PRIX32
|
||||
") to "
|
||||
"NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR",
|
||||
static_cast<uint32_t>(aResultCode))
|
||||
.get());
|
||||
|
||||
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -2107,8 +2092,7 @@ NormalFileHandleOp::SendFailureResult(nsresult aResultCode)
|
||||
|
||||
if (!IsActorDestroyed()) {
|
||||
result =
|
||||
PBackgroundFileRequestParent::Send__delete__(
|
||||
this, ClampResultCode(aResultCode));
|
||||
PBackgroundFileRequestParent::Send__delete__(this, aResultCode);
|
||||
}
|
||||
|
||||
DEBUGONLY(mResponseSent = true;)
|
||||
@@ -2270,10 +2254,6 @@ CopyFileHandleOp::DoFileWork(FileHandle* aFileHandle)
|
||||
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
} while (true);
|
||||
|
||||
if (mOffset < mSize) {
|
||||
// end-of-file reached
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(mOffset == mSize);
|
||||
|
||||
if (mRead) {
|
||||
@@ -2598,25 +2578,6 @@ TruncateOp::DoFileWork(FileHandle* aFileHandle)
|
||||
nsCOMPtr<nsISeekableStream> sstream = do_QueryInterface(mFileStream);
|
||||
MOZ_ASSERT(sstream);
|
||||
|
||||
if (mParams.offset()) {
|
||||
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mFileStream);
|
||||
MOZ_ASSERT(fileMetadata);
|
||||
|
||||
int64_t size;
|
||||
nsresult rv = fileMetadata->GetSize(&size);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(size >= 0);
|
||||
|
||||
if (mParams.offset() > static_cast<uint64_t>(size)) {
|
||||
// Cannot extend the size of a file through truncate.
|
||||
return NS_ERROR_DOM_INVALID_MODIFICATION_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX If we allowed truncate to extend the file size, we would to ensure that
|
||||
// the quota limit is checked, e.g. by making FileQuotaStream override Seek.
|
||||
nsresult rv = sstream->Seek(nsISeekableStream::NS_SEEK_SET, mParams.offset());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
||||
@@ -110,12 +110,15 @@ DocAllResultMatch(Element* aElement, int32_t aNamespaceID, nsIAtom* aAtom,
|
||||
nsContentList*
|
||||
HTMLAllCollection::GetDocumentAllList(const nsAString& aID)
|
||||
{
|
||||
return mNamedMap.LookupForAdd(aID).OrInsert(
|
||||
[this, &aID] () {
|
||||
nsCOMPtr<nsIAtom> id = NS_Atomize(aID);
|
||||
return new nsContentList(mDocument, DocAllResultMatch, nullptr,
|
||||
nullptr, true, id);
|
||||
});
|
||||
if (nsContentList* docAllList = mNamedMap.GetWeak(aID)) {
|
||||
return docAllList;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> id = NS_Atomize(aID);
|
||||
RefPtr<nsContentList> docAllList =
|
||||
new nsContentList(mDocument, DocAllResultMatch, nullptr, nullptr, true, id);
|
||||
mNamedMap.Put(aID, docAllList);
|
||||
return docAllList;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -276,6 +276,41 @@ HTMLFormElement::Submit()
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
|
||||
void
|
||||
HTMLFormElement::RequestSubmit(nsGenericHTMLElement* aSubmitter,
|
||||
ErrorResult& aRv) {
|
||||
// 1. If submitter is not null, then:
|
||||
if (aSubmitter) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryObject(aSubmitter);
|
||||
|
||||
// 1.1. If submitter is not a submit button, then throw a TypeError.
|
||||
if (!fc || !fc->IsSubmitControl()) {
|
||||
aRv.ThrowTypeError<MSG_NOT_SUBMIT_BUTTON>();
|
||||
return;
|
||||
}
|
||||
|
||||
// 1.2. If submitter's form owner is not this form element, then throw a
|
||||
// "NotFoundError" DOMException.
|
||||
if (fc->GetFormElement() != this) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Otherwise, set submitter to this form element.
|
||||
// 3. Submit this form element, from submitter.
|
||||
// We go through the presShell here for the corner case a submit event
|
||||
// is pending while the window is being destroyed.
|
||||
InternalFormEvent event(true, eFormSubmit);
|
||||
event.mOriginator = aSubmitter;
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsCOMPtr<nsIPresShell> presShell = GetComposedDoc()->GetShell();
|
||||
if (MOZ_LIKELY(presShell)) {
|
||||
presShell->HandleDOMEventWithTarget(this, &event, &status);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLFormElement::Reset()
|
||||
{
|
||||
|
||||
@@ -391,6 +391,19 @@ public:
|
||||
|
||||
void Submit(ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Requests to submit the form. Unlike submit(), this method includes
|
||||
* interactive constraint validation and firing a submit event,
|
||||
* either of which can cancel submission.
|
||||
*
|
||||
* @param aSubmitter The submitter argument can be used to point to a specific
|
||||
* submit button.
|
||||
* @param aRv An ErrorResult.
|
||||
* @see
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
|
||||
*/
|
||||
void RequestSubmit(nsGenericHTMLElement* aSubmitter, ErrorResult& aRv);
|
||||
|
||||
// XPCOM Reset() is OK
|
||||
|
||||
bool CheckValidity()
|
||||
|
||||
@@ -5093,14 +5093,6 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
|
||||
uint8_t oldType = mType;
|
||||
MOZ_ASSERT(oldType != aNewType);
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
// Input element can represent very different kinds of UIs, and we may
|
||||
// need to flush styling even when focusing the already focused input
|
||||
// element.
|
||||
fm->NeedsFlushBeforeEventHandling(this);
|
||||
}
|
||||
|
||||
if (aNewType == NS_FORM_INPUT_FILE || oldType == NS_FORM_INPUT_FILE) {
|
||||
// Strictly speaking, we only need to clear files on going _to_ or _from_
|
||||
// the NS_FORM_INPUT_FILE type, not both, since we'll never confuse values
|
||||
|
||||
@@ -3977,10 +3977,6 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
|
||||
NotifyOwnerDocumentActivityChanged();
|
||||
UpdateAudioChannelPlayingState();
|
||||
|
||||
if (mPausedForInactiveDocumentOrChannel) {
|
||||
mDecoder->Suspend();
|
||||
}
|
||||
|
||||
if (!mPaused) {
|
||||
SetPlayedOrSeeked(true);
|
||||
if (!mPausedForInactiveDocumentOrChannel) {
|
||||
|
||||
+14
-47
@@ -105,22 +105,6 @@ namespace indexedDB {
|
||||
[1, 2] // 0x60 bf f0 0 0 0 0 0 0 0x10 c0
|
||||
[[]] // 0x80
|
||||
*/
|
||||
|
||||
// |aPos| should point to the type indicator.
|
||||
// The returned length doesn't include the type indicator
|
||||
// or the terminator.
|
||||
static size_t LengthOfEncodedBinary(const unsigned char* aPos,
|
||||
const unsigned char* aEnd) {
|
||||
MOZ_ASSERT(*aPos % Key::eMaxType == Key::eBinary, "Don't call me!");
|
||||
auto iter = ++aPos;
|
||||
for (; iter < aEnd && *iter != Key::eTerminator; ++iter) {
|
||||
if (*iter & 0x80) {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
return iter - aPos;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
|
||||
{
|
||||
@@ -145,16 +129,11 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
|
||||
bool canShareBuffers = true;
|
||||
while (it < end) {
|
||||
auto type = *it % eMaxType;
|
||||
if (type == eTerminator) {
|
||||
if (type == eTerminator || type == eArray) {
|
||||
it++;
|
||||
} else if (type == eFloat || type == eDate) {
|
||||
it++;
|
||||
it += std::min(sizeof(uint64_t), size_t(end - it));
|
||||
} else if (type == eBinary) {
|
||||
// skip all binary data
|
||||
auto binaryLength = LengthOfEncodedBinary(it, end);
|
||||
it++;
|
||||
it += binaryLength;
|
||||
} else {
|
||||
// We have a string!
|
||||
canShareBuffers = false;
|
||||
@@ -176,7 +155,9 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
std::copy(start, it, buffer);
|
||||
while (start < it) {
|
||||
*(buffer++) = *(start++);
|
||||
}
|
||||
}
|
||||
|
||||
// Now continue decoding
|
||||
@@ -185,38 +166,24 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
|
||||
uint32_t oldLen = aTarget.mBuffer.Length();
|
||||
auto type = *it % eMaxType;
|
||||
|
||||
// Note: Do not modify |it| before calling |updateBufferAndIter|;
|
||||
// |byteCount| doesn't include the type indicator
|
||||
auto updateBufferAndIter = [&](size_t byteCount) -> bool {
|
||||
if (!aTarget.mBuffer.GetMutableData(&buffer, oldLen + 1 + byteCount)) {
|
||||
return false;
|
||||
}
|
||||
buffer += oldLen;
|
||||
|
||||
// should also copy the type indicator at the begining
|
||||
std::copy_n(it, byteCount + 1, buffer);
|
||||
it += (byteCount + 1);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (type == eTerminator) {
|
||||
if (type == eTerminator || type == eArray) {
|
||||
// Copy array TypeID and terminator from raw key
|
||||
if (!updateBufferAndIter(0)) {
|
||||
if (!aTarget.mBuffer.GetMutableData(&buffer, oldLen + 1)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*(buffer + oldLen) = *(it++);
|
||||
} else if (type == eFloat || type == eDate) {
|
||||
// Copy number from raw key
|
||||
const size_t byteCount = std::min(sizeof(uint64_t), size_t(end - it - 1));
|
||||
|
||||
if (!updateBufferAndIter(byteCount)) {
|
||||
if (!aTarget.mBuffer.GetMutableData(&buffer,
|
||||
oldLen + 1 + sizeof(uint64_t))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else if (type == eBinary) {
|
||||
// skip all binary data
|
||||
auto binaryLength = LengthOfEncodedBinary(it, end);
|
||||
buffer += oldLen;
|
||||
*(buffer++) = *(it++);
|
||||
|
||||
if (!updateBufferAndIter(binaryLength)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
const size_t byteCount = std::min(sizeof(uint64_t), size_t(end - it));
|
||||
for (size_t count = 0; count < byteCount; count++) {
|
||||
*(buffer++) = (*it++);
|
||||
}
|
||||
} else {
|
||||
// Decode string and reencode
|
||||
|
||||
@@ -371,6 +371,9 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
|
||||
case TrackType::kVideoTrack: {
|
||||
// Decoders use the layers backend to decide if they can use hardware decoding,
|
||||
// so specify LAYERS_NONE if we want to forcibly disable it.
|
||||
using Option = CreateDecoderParams::Option;
|
||||
using OptionSet = CreateDecoderParams::OptionSet;
|
||||
|
||||
data.mDecoder = mOwner->mPlatform->CreateDecoder({
|
||||
ownerData.mInfo
|
||||
? *ownerData.mInfo->GetAsVideoInfo()
|
||||
@@ -383,7 +386,10 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack)
|
||||
mOwner->mCrashHelper,
|
||||
#endif
|
||||
ownerData.mIsBlankDecode,
|
||||
&result
|
||||
&result,
|
||||
OptionSet(ownerData.mHardwareDecodingDisabled
|
||||
? Option::HardwareDecoderNotAllowed
|
||||
: Option::Default)
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -921,6 +927,8 @@ MediaFormatReader::NotifyNewOutput(TrackType aTrack, MediaData* aSample)
|
||||
decoder.mOutput.AppendElement(aSample);
|
||||
decoder.mNumSamplesOutput++;
|
||||
decoder.mNumOfConsecutiveError = 0;
|
||||
// We have decoded our first frame, we can now start to skip future errors.
|
||||
decoder.mFirstFrameTime.reset();
|
||||
ScheduleUpdate(aTrack);
|
||||
}
|
||||
|
||||
@@ -1415,7 +1423,7 @@ MediaFormatReader::Update(TrackType aTrack)
|
||||
RefPtr<MediaData> output = decoder.mOutput[0];
|
||||
decoder.mOutput.RemoveElementAt(0);
|
||||
decoder.mSizeOfQueue -= 1;
|
||||
decoder.mLastSampleTime =
|
||||
decoder.mLastDecodedSampleTime =
|
||||
Some(TimeInterval(TimeUnit::FromMicroseconds(output->mTime),
|
||||
TimeUnit::FromMicroseconds(output->GetEndTime())));
|
||||
decoder.mNumSamplesOutputTotal++;
|
||||
@@ -1463,14 +1471,14 @@ MediaFormatReader::Update(TrackType aTrack)
|
||||
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
|
||||
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
|
||||
} else if (decoder.mWaitingForData) {
|
||||
if (wasDraining && decoder.mLastSampleTime &&
|
||||
if (wasDraining && decoder.mLastDecodedSampleTime &&
|
||||
!decoder.mNextStreamSourceID) {
|
||||
// We have completed draining the decoder following WaitingForData.
|
||||
// Set up the internal seek machinery to be able to resume from the
|
||||
// last sample decoded.
|
||||
LOG("Seeking to last sample time: %lld",
|
||||
decoder.mLastSampleTime.ref().mStart.ToMicroseconds());
|
||||
InternalSeek(aTrack, InternalSeekTarget(decoder.mLastSampleTime.ref(), true));
|
||||
decoder.mLastDecodedSampleTime.ref().mStart.ToMicroseconds());
|
||||
InternalSeek(aTrack, InternalSeekTarget(decoder.mLastDecodedSampleTime.ref(), true));
|
||||
}
|
||||
if (!decoder.mReceivedNewData) {
|
||||
LOG("Rejecting %s promise: WAITING_FOR_DATA", TrackTypeToStr(aTrack));
|
||||
@@ -1506,24 +1514,52 @@ MediaFormatReader::Update(TrackType aTrack)
|
||||
|
||||
if (decoder.mError && !decoder.HasFatalError()) {
|
||||
decoder.mDecodePending = false;
|
||||
bool needsNewDecoder = decoder.mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
|
||||
|
||||
MOZ_RELEASE_ASSERT(!decoder.HasInternalSeekPending(),
|
||||
"No error can occur while an internal seek is pending");
|
||||
|
||||
nsCString error;
|
||||
bool firstFrameDecodingFailedWithHardware =
|
||||
decoder.mFirstFrameTime &&
|
||||
decoder.mError.ref() == NS_ERROR_DOM_MEDIA_DECODE_ERR &&
|
||||
decoder.mDecoder && decoder.mDecoder->IsHardwareAccelerated(error) &&
|
||||
!decoder.mHardwareDecodingDisabled;
|
||||
bool needsNewDecoder =
|
||||
decoder.mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER ||
|
||||
firstFrameDecodingFailedWithHardware;
|
||||
if (!needsNewDecoder && ++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
|
||||
NotifyError(aTrack, decoder.mError.ref());
|
||||
return;
|
||||
}
|
||||
if (firstFrameDecodingFailedWithHardware) {
|
||||
decoder.mHardwareDecodingDisabled = true;
|
||||
}
|
||||
decoder.mError.reset();
|
||||
LOG("%s decoded error count %d", TrackTypeToStr(aTrack),
|
||||
decoder.mNumOfConsecutiveError);
|
||||
|
||||
if (needsNewDecoder) {
|
||||
LOG("Error: Need new decoder");
|
||||
decoder.ShutdownDecoder();
|
||||
}
|
||||
if (decoder.mFirstFrameTime) {
|
||||
TimeInterval seekInterval = TimeInterval(decoder.mFirstFrameTime.ref(),
|
||||
decoder.mFirstFrameTime.ref());
|
||||
InternalSeek(aTrack, InternalSeekTarget(seekInterval, false));
|
||||
return;
|
||||
}
|
||||
|
||||
media::TimeUnit nextKeyframe;
|
||||
if (aTrack == TrackType::kVideoTrack && !decoder.HasInternalSeekPending() &&
|
||||
NS_SUCCEEDED(decoder.mTrackDemuxer->GetNextRandomAccessPoint(&nextKeyframe))) {
|
||||
if (needsNewDecoder) {
|
||||
decoder.ShutdownDecoder();
|
||||
}
|
||||
SkipVideoDemuxToNextKeyFrame(decoder.mLastSampleTime.refOr(TimeInterval()).Length());
|
||||
NS_SUCCEEDED(decoder.mTrackDemuxer->GetNextRandomAccessPoint(&nextKeyframe)) &&
|
||||
!nextKeyframe.IsInfinite()) {
|
||||
SkipVideoDemuxToNextKeyFrame(decoder.mLastDecodedSampleTime.refOr(TimeInterval()).Length());
|
||||
return;
|
||||
} else if (aTrack == TrackType::kAudioTrack) {
|
||||
decoder.Flush();
|
||||
} else {
|
||||
// We can't recover from this error.
|
||||
NotifyError(aTrack, NS_ERROR_DOM_MEDIA_FATAL_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1664,6 +1700,7 @@ MediaFormatReader::ResetDecode(TrackSet aTracks)
|
||||
|
||||
if (HasVideo() && aTracks.contains(TrackInfo::kVideoTrack)) {
|
||||
mVideo.ResetDemuxer();
|
||||
mVideo.mFirstFrameTime = Some(media::TimeUnit());
|
||||
Reset(TrackInfo::kVideoTrack);
|
||||
if (mVideo.HasPromise()) {
|
||||
mVideo.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
@@ -1672,6 +1709,7 @@ MediaFormatReader::ResetDecode(TrackSet aTracks)
|
||||
|
||||
if (HasAudio() && aTracks.contains(TrackInfo::kAudioTrack)) {
|
||||
mAudio.ResetDemuxer();
|
||||
mVideo.mFirstFrameTime = Some(media::TimeUnit());
|
||||
Reset(TrackInfo::kAudioTrack);
|
||||
if (mAudio.HasPromise()) {
|
||||
mAudio.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
@@ -2030,6 +2068,7 @@ MediaFormatReader::OnVideoSeekCompleted(media::TimeUnit aTime)
|
||||
LOGV("Video seeked to %lld", aTime.ToMicroseconds());
|
||||
mVideo.mSeekRequest.Complete();
|
||||
|
||||
mVideo.mFirstFrameTime = Some(aTime);
|
||||
mPreviousDecodedKeyframeTime_us = sNoPreviousDecodedKeyframe;
|
||||
|
||||
SetVideoDecodeThreshold();
|
||||
@@ -2111,6 +2150,7 @@ MediaFormatReader::OnAudioSeekCompleted(media::TimeUnit aTime)
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
LOGV("Audio seeked to %lld", aTime.ToMicroseconds());
|
||||
mAudio.mSeekRequest.Complete();
|
||||
mAudio.mFirstFrameTime = Some(aTime);
|
||||
mPendingSeekTime.reset();
|
||||
mSeekPromise.Resolve(aTime, __func__);
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@ private:
|
||||
, mDrainComplete(false)
|
||||
, mNumOfConsecutiveError(0)
|
||||
, mMaxConsecutiveError(aNumOfMaxError)
|
||||
, mFirstFrameTime(Some(media::TimeUnit()))
|
||||
, mNumSamplesInput(0)
|
||||
, mNumSamplesOutput(0)
|
||||
, mNumSamplesOutputTotal(0)
|
||||
@@ -243,6 +244,7 @@ private:
|
||||
, mIsHardwareAccelerated(false)
|
||||
, mLastStreamSourceID(UINT32_MAX)
|
||||
, mIsBlankDecode(false)
|
||||
, mHardwareDecodingDisabled(false)
|
||||
{}
|
||||
|
||||
MediaFormatReader* mOwner;
|
||||
@@ -316,6 +318,11 @@ private:
|
||||
|
||||
uint32_t mNumOfConsecutiveError;
|
||||
uint32_t mMaxConsecutiveError;
|
||||
// Set when we haven't yet decoded the first frame.
|
||||
// Cleared once the first frame has been decoded.
|
||||
// This is used to determine, upon error, if we should try again to decode
|
||||
// the frame, or skip to the next keyframe.
|
||||
Maybe<media::TimeUnit> mFirstFrameTime;
|
||||
|
||||
Maybe<MediaResult> mError;
|
||||
bool HasFatalError() const
|
||||
@@ -341,8 +348,8 @@ private:
|
||||
// Used for internal seeking when a change of stream is detected or when
|
||||
// encountering data discontinuity.
|
||||
Maybe<InternalSeekTarget> mTimeThreshold;
|
||||
// Time of last sample returned.
|
||||
Maybe<media::TimeInterval> mLastSampleTime;
|
||||
// Time of last decoded sample returned.
|
||||
Maybe<media::TimeInterval> mLastDecodedSampleTime;
|
||||
|
||||
// Decoded samples returned my mDecoder awaiting being returned to
|
||||
// state machine upon request.
|
||||
@@ -405,7 +412,7 @@ private:
|
||||
mDraining = false;
|
||||
mDrainComplete = false;
|
||||
mTimeThreshold.reset();
|
||||
mLastSampleTime.reset();
|
||||
mLastDecodedSampleTime.reset();
|
||||
mOutput.Clear();
|
||||
mNumSamplesInput = 0;
|
||||
mNumSamplesOutput = 0;
|
||||
@@ -437,6 +444,7 @@ private:
|
||||
Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
|
||||
// Use BlankDecoderModule or not.
|
||||
bool mIsBlankDecode;
|
||||
bool mHardwareDecodingDisabled;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define GMP_DEVICE_BINDING_h_
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
@@ -963,7 +963,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
|
||||
// 1. Update the duration attribute if it currently equals NaN.
|
||||
// Those steps are performed by the MediaSourceDecoder::SetInitialDuration
|
||||
AbstractThread::MainThread()->Dispatch(NewRunnableMethod<int64_t>
|
||||
(mParentDecoder.get(),
|
||||
(mParentDecoder,
|
||||
&MediaSourceDecoder::SetInitialDuration,
|
||||
duration ? duration : -1));
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ImageContainer.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/KnowsCompositor.h"
|
||||
@@ -47,6 +48,13 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
|
||||
: mConfig(aConfig)
|
||||
{}
|
||||
|
||||
enum class Option
|
||||
{
|
||||
Default,
|
||||
HardwareDecoderNotAllowed,
|
||||
};
|
||||
using OptionSet = EnumSet<Option>;
|
||||
|
||||
template <typename T1, typename... Ts>
|
||||
CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
|
||||
: mConfig(aConfig)
|
||||
@@ -85,6 +93,7 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
|
||||
RefPtr<GMPCrashHelper> mCrashHelper;
|
||||
#endif
|
||||
bool mUseBlankDecoder = false;
|
||||
OptionSet mOptions = OptionSet(Option::Default);
|
||||
|
||||
private:
|
||||
void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
|
||||
@@ -96,6 +105,7 @@ private:
|
||||
void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
|
||||
#endif
|
||||
void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; }
|
||||
void Set(OptionSet aOptions) { mOptions = aOptions; }
|
||||
void Set(layers::KnowsCompositor* aKnowsCompositor) { mKnowsCompositor = aKnowsCompositor; }
|
||||
template <typename T1, typename T2, typename... Ts>
|
||||
void Set(T1&& a1, T2&& a2, Ts&&... args)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "VPXDecoder.h"
|
||||
#include "mp4_demuxer/BitReader.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "nsError.h"
|
||||
#include "TimeUnits.h"
|
||||
@@ -383,5 +384,32 @@ VPXDecoder::GetFrameSize(Span<const uint8_t> aBuffer, Codec aCodec)
|
||||
return nsIntSize(si.w, si.h);
|
||||
}
|
||||
|
||||
/* static */
|
||||
int
|
||||
VPXDecoder::GetVP9Profile(Span<const uint8_t> aBuffer)
|
||||
{
|
||||
if (aBuffer.Length() < 2) {
|
||||
// Can't be good.
|
||||
return -1;
|
||||
}
|
||||
mp4_demuxer::BitReader br(aBuffer.Elements(), aBuffer.Length() * 8);
|
||||
|
||||
uint32_t frameMarker = br.ReadBits(2); // frame_marker
|
||||
if (frameMarker != 2) {
|
||||
// That's not a valid vp9 header.
|
||||
return -1;
|
||||
}
|
||||
uint32_t profile = br.ReadBits(1); // profile_low_bit
|
||||
profile |= br.ReadBits(1) << 1; // profile_high_bit
|
||||
if (profile == 3) {
|
||||
profile += br.ReadBits(1); // reserved_zero
|
||||
if (profile > 3) {
|
||||
// reserved_zero wasn't zero.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
#undef LOG
|
||||
@@ -53,6 +53,10 @@ public:
|
||||
// Return the frame dimensions for a sample for the specified codec.
|
||||
static nsIntSize GetFrameSize(Span<const uint8_t> aBuffer, Codec aCodec);
|
||||
|
||||
// Return the VP9 profile as per https://www.webmproject.org/vp9/profiles/
|
||||
// Return negative value if error.
|
||||
static int GetVP9Profile(Span<const uint8_t> aBuffer);
|
||||
|
||||
private:
|
||||
void ProcessDecode(MediaRawData* aSample);
|
||||
MediaResult DoDecode(MediaRawData* aSample);
|
||||
|
||||
@@ -40,11 +40,7 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig,
|
||||
, mMaxRefFrames(mp4_demuxer::H264::ComputeMaxRefFrames(aConfig.mExtraData))
|
||||
, mImageContainer(aImageContainer)
|
||||
, mIsShutDown(false)
|
||||
#ifdef MOZ_WIDGET_UIKIT
|
||||
, mUseSoftwareImages(true)
|
||||
#else
|
||||
, mUseSoftwareImages(false)
|
||||
#endif
|
||||
, mIsFlushing(false)
|
||||
, mMonitor("AppleVideoDecoder")
|
||||
, mFormat(nullptr)
|
||||
@@ -356,7 +352,6 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
|
||||
// Unlock the returned image data.
|
||||
CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
|
||||
} else {
|
||||
#ifndef MOZ_WIDGET_UIKIT
|
||||
IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage);
|
||||
MOZ_ASSERT(surface, "Decoder didn't return an IOSurface backed buffer");
|
||||
|
||||
@@ -373,9 +368,6 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
|
||||
aFrameRef.is_sync_point,
|
||||
aFrameRef.decode_timestamp.ToMicroseconds(),
|
||||
visible);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
|
||||
@@ -91,11 +91,12 @@ WMFDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoPtr<WMFVideoMFTManager> manager(
|
||||
new WMFVideoMFTManager(aParams.VideoConfig(),
|
||||
aParams.mKnowsCompositor,
|
||||
aParams.mImageContainer,
|
||||
sDXVAEnabled));
|
||||
nsAutoPtr<WMFVideoMFTManager> manager(new WMFVideoMFTManager(
|
||||
aParams.VideoConfig(),
|
||||
aParams.mKnowsCompositor,
|
||||
aParams.mImageContainer,
|
||||
sDXVAEnabled && !aParams.mOptions.contains(
|
||||
CreateDecoderParams::Option::HardwareDecoderNotAllowed)));
|
||||
|
||||
if (!manager->Init()) {
|
||||
return nullptr;
|
||||
|
||||
@@ -576,6 +576,16 @@ WMFVideoMFTManager::Input(MediaRawData* aSample)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (mStreamType == VP9 && aSample->mKeyframe) {
|
||||
// Check the VP9 profile. the VP9 MFT can only handle correctly profile 0
|
||||
// and 2 (yuv420 8/10/12 bits)
|
||||
int profile =
|
||||
VPXDecoder::GetVP9Profile(MakeSpan(aSample->Data(), aSample->Size()));
|
||||
if (profile != 0 && profile != 2) {
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = mDecoder->CreateInputSample(aSample->Data(),
|
||||
uint32_t(aSample->Size()),
|
||||
aSample->mTime,
|
||||
@@ -990,7 +1000,12 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||
aOutData = frame;
|
||||
// Set the potentially corrected pts and duration.
|
||||
aOutData->mTime = pts.ToMicroseconds();
|
||||
aOutData->mDuration = duration.ToMicroseconds();
|
||||
// The VP9 decoder doesn't provide a valid duration. AS VP9 doesn't have a
|
||||
// concept of pts vs dts and have no latency. We can as such use the last
|
||||
// known input duration.
|
||||
aOutData->mDuration = (mStreamType == VP9 && duration == media::TimeUnit())
|
||||
? mLastDuration
|
||||
: duration.ToMicroseconds();
|
||||
|
||||
if (mNullOutputCount) {
|
||||
mGotValidOutputAfterNullOutput = true;
|
||||
|
||||
@@ -100,6 +100,45 @@ public:
|
||||
uint32_t mChunksToProcess = 0;
|
||||
};
|
||||
|
||||
/* static */ already_AddRefed<AnalyserNode>
|
||||
AnalyserNode::Create(AudioContext& aAudioContext,
|
||||
const AnalyserOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AnalyserNode> analyserNode = new AnalyserNode(&aAudioContext);
|
||||
|
||||
analyserNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
analyserNode->SetFftSize(aOptions.mFftSize, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
analyserNode->SetMinDecibels(aOptions.mMinDecibels, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
analyserNode->SetMaxDecibels(aOptions.mMaxDecibels, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
analyserNode->SetSmoothingTimeConstant(aOptions.mSmoothingTimeConstant, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return analyserNode.forget();
|
||||
}
|
||||
|
||||
AnalyserNode::AnalyserNode(AudioContext* aContext)
|
||||
: AudioNode(aContext,
|
||||
1,
|
||||
|
||||
@@ -14,16 +14,26 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct AnalyserOptions;
|
||||
|
||||
class AnalyserNode final : public AudioNode
|
||||
{
|
||||
public:
|
||||
explicit AnalyserNode(AudioContext* aContext);
|
||||
static already_AddRefed<AnalyserNode>
|
||||
Create(AudioContext& aAudioContext, const AnalyserOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<AnalyserNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const AnalyserOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
void GetFloatFrequencyData(const Float32Array& aArray);
|
||||
void GetByteFrequencyData(const Uint8Array& aArray);
|
||||
void GetFloatTimeDomainData(const Float32Array& aArray);
|
||||
@@ -61,10 +71,9 @@ public:
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
protected:
|
||||
~AnalyserNode() {}
|
||||
|
||||
private:
|
||||
~AnalyserNode() = default;
|
||||
|
||||
friend class AnalyserNodeEngine;
|
||||
void AppendChunk(const AudioChunk& aChunk);
|
||||
bool AllocateBuffer();
|
||||
@@ -73,6 +82,8 @@ private:
|
||||
void GetTimeDomainData(float* aData, size_t aLength);
|
||||
|
||||
private:
|
||||
explicit AnalyserNode(AudioContext* aContext);
|
||||
|
||||
FFTBlock mAnalysisBlock;
|
||||
nsTArray<AudioChunk> mChunks;
|
||||
double mMinDecibels;
|
||||
|
||||
@@ -178,6 +178,24 @@ AudioBuffer::~AudioBuffer()
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<AudioBuffer>
|
||||
AudioBuffer::Constructor(const GlobalObject& aGlobal,
|
||||
AudioContext& aAudioContext,
|
||||
const AudioBufferOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aOptions.mNumberOfChannels) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float sampleRate = aOptions.mSampleRate.WasPassed()
|
||||
? aOptions.mSampleRate.Value()
|
||||
: aAudioContext.SampleRate();
|
||||
return Create(&aAudioContext, aOptions.mNumberOfChannels, aOptions.mLength,
|
||||
sampleRate, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBuffer::ClearJSChannels()
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ class ThreadSharedFloatArrayBufferList;
|
||||
|
||||
namespace dom {
|
||||
|
||||
struct AudioBufferOptions;
|
||||
class AudioContext;
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,10 @@ public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioBuffer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioBuffer)
|
||||
|
||||
static already_AddRefed<AudioBuffer>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const AudioBufferOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
nsPIDOMWindowInner* GetParentObject() const
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> parentObject = do_QueryReferent(mOwnerWindow);
|
||||
@@ -134,4 +139,3 @@ protected:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -607,10 +607,30 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
|
||||
mStream->AddMainThreadListener(this);
|
||||
}
|
||||
|
||||
AudioBufferSourceNode::~AudioBufferSourceNode()
|
||||
/* static */ already_AddRefed<AudioBufferSourceNode>
|
||||
AudioBufferSourceNode::Create(JSContext* aCx, AudioContext& aAudioContext,
|
||||
const AudioBufferSourceOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
}
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AudioBufferSourceNode> audioNode = new AudioBufferSourceNode(&aAudioContext);
|
||||
|
||||
if (aOptions.mBuffer.WasPassed()) {
|
||||
MOZ_ASSERT(aCx);
|
||||
audioNode->SetBuffer(aCx, aOptions.mBuffer.Value());
|
||||
}
|
||||
|
||||
audioNode->Detune()->SetValue(aOptions.mDetune);
|
||||
audioNode->SetLoop(aOptions.mLoop);
|
||||
audioNode->SetLoopEnd(aOptions.mLoopEnd);
|
||||
audioNode->SetLoopStart(aOptions.mLoopStart);
|
||||
audioNode->PlaybackRate()->SetValue(aOptions.mPlaybackRate);
|
||||
|
||||
return audioNode.forget();
|
||||
}
|
||||
void
|
||||
AudioBufferSourceNode::DestroyMediaStream()
|
||||
{
|
||||
|
||||
@@ -12,13 +12,16 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct AudioBufferSourceOptions;
|
||||
class AudioParam;
|
||||
|
||||
class AudioBufferSourceNode final : public AudioNode,
|
||||
public MainThreadMediaStreamListener
|
||||
class AudioBufferSourceNode final : public AudioNode
|
||||
, public MainThreadMediaStreamListener
|
||||
{
|
||||
public:
|
||||
explicit AudioBufferSourceNode(AudioContext* aContext);
|
||||
static already_AddRefed<AudioBufferSourceNode>
|
||||
Create(JSContext* aCx, AudioContext& aAudioContext,
|
||||
const AudioBufferSourceOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
void DestroyMediaStream() override;
|
||||
|
||||
@@ -33,6 +36,13 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioBufferSourceNode, AudioNode)
|
||||
|
||||
static already_AddRefed<AudioBufferSourceNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const AudioBufferSourceOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aGlobal.Context(), aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void Start(double aWhen, double aOffset,
|
||||
@@ -98,10 +108,10 @@ public:
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
protected:
|
||||
virtual ~AudioBufferSourceNode();
|
||||
|
||||
private:
|
||||
explicit AudioBufferSourceNode(AudioContext* aContext);
|
||||
~AudioBufferSourceNode() = default;
|
||||
|
||||
friend class AudioBufferSourceNodeEngine;
|
||||
// START is sent during Start().
|
||||
// STOP is sent during Stop().
|
||||
@@ -129,7 +139,6 @@ private:
|
||||
void SendBufferParameterToStream(JSContext* aCx);
|
||||
void SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream);
|
||||
|
||||
private:
|
||||
double mLoopStart;
|
||||
double mLoopEnd;
|
||||
double mOffset;
|
||||
@@ -145,4 +154,3 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,10 +11,26 @@
|
||||
#include "mozilla/OwningNonNull.h"
|
||||
|
||||
#include "mozilla/dom/AnalyserNode.h"
|
||||
#include "mozilla/dom/AnalyserNodeBinding.h"
|
||||
#include "mozilla/dom/AudioBufferSourceNodeBinding.h"
|
||||
#include "mozilla/dom/AudioContextBinding.h"
|
||||
#include "mozilla/dom/BiquadFilterNodeBinding.h"
|
||||
#include "mozilla/dom/ChannelMergerNodeBinding.h"
|
||||
#include "mozilla/dom/ChannelSplitterNodeBinding.h"
|
||||
#include "mozilla/dom/ConvolverNodeBinding.h"
|
||||
#include "mozilla/dom/DelayNodeBinding.h"
|
||||
#include "mozilla/dom/DynamicsCompressorNodeBinding.h"
|
||||
#include "mozilla/dom/GainNodeBinding.h"
|
||||
#include "mozilla/dom/IIRFilterNodeBinding.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/MediaElementAudioSourceNodeBinding.h"
|
||||
#include "mozilla/dom/MediaStreamAudioSourceNodeBinding.h"
|
||||
#include "mozilla/dom/OfflineAudioContextBinding.h"
|
||||
#include "mozilla/dom/OscillatorNodeBinding.h"
|
||||
#include "mozilla/dom/PannerNodeBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/StereoPannerNodeBinding.h"
|
||||
#include "mozilla/dom/WaveShaperNodeBinding.h"
|
||||
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioBufferSourceNode.h"
|
||||
@@ -245,13 +261,9 @@ bool AudioContext::CheckClosed(ErrorResult& aRv)
|
||||
already_AddRefed<AudioBufferSourceNode>
|
||||
AudioContext::CreateBufferSource(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AudioBufferSourceNode> bufferNode =
|
||||
new AudioBufferSourceNode(this);
|
||||
return bufferNode.forget();
|
||||
return AudioBufferSourceNode::Create(nullptr, *this,
|
||||
AudioBufferSourceOptions(),
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<ConstantSourceNode>
|
||||
@@ -303,18 +315,8 @@ bool IsValidBufferSize(uint32_t aBufferSize) {
|
||||
already_AddRefed<MediaStreamAudioDestinationNode>
|
||||
AudioContext::CreateMediaStreamDestination(ErrorResult& aRv)
|
||||
{
|
||||
if (mIsOffline) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<MediaStreamAudioDestinationNode> node =
|
||||
new MediaStreamAudioDestinationNode(this);
|
||||
return node.forget();
|
||||
return MediaStreamAudioDestinationNode::Create(*this, AudioNodeOptions(),
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<ScriptProcessorNode>
|
||||
@@ -344,181 +346,93 @@ AudioContext::CreateScriptProcessor(uint32_t aBufferSize,
|
||||
already_AddRefed<AnalyserNode>
|
||||
AudioContext::CreateAnalyser(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AnalyserNode> analyserNode = new AnalyserNode(this);
|
||||
return analyserNode.forget();
|
||||
return AnalyserNode::Create(*this, AnalyserOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<StereoPannerNode>
|
||||
AudioContext::CreateStereoPanner(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<StereoPannerNode> stereoPannerNode = new StereoPannerNode(this);
|
||||
return stereoPannerNode.forget();
|
||||
return StereoPannerNode::Create(*this, StereoPannerOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaElementAudioSourceNode>
|
||||
AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mIsOffline) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
MediaElementAudioSourceOptions options;
|
||||
options.mMediaElement = aMediaElement;
|
||||
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DOMMediaStream> stream =
|
||||
aMediaElement.CaptureAudio(aRv, mDestination->Stream()->Graph());
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return MediaElementAudioSourceNode::Create(this, stream, aRv);
|
||||
return MediaElementAudioSourceNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaStreamAudioSourceNode>
|
||||
AudioContext::CreateMediaStreamSource(DOMMediaStream& aMediaStream,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mIsOffline) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
MediaStreamAudioSourceOptions options;
|
||||
options.mMediaStream = aMediaStream;
|
||||
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return MediaStreamAudioSourceNode::Create(this, &aMediaStream, aRv);
|
||||
return MediaStreamAudioSourceNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<GainNode>
|
||||
AudioContext::CreateGain(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<GainNode> gainNode = new GainNode(this);
|
||||
return gainNode.forget();
|
||||
return GainNode::Create(*this, GainOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<WaveShaperNode>
|
||||
AudioContext::CreateWaveShaper(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<WaveShaperNode> waveShaperNode = new WaveShaperNode(this);
|
||||
return waveShaperNode.forget();
|
||||
return WaveShaperNode::Create(*this, WaveShaperOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<DelayNode>
|
||||
AudioContext::CreateDelay(double aMaxDelayTime, ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aMaxDelayTime > 0. && aMaxDelayTime < 180.) {
|
||||
RefPtr<DelayNode> delayNode = new DelayNode(this, aMaxDelayTime);
|
||||
return delayNode.forget();
|
||||
}
|
||||
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
DelayOptions options;
|
||||
options.mMaxDelayTime = aMaxDelayTime;
|
||||
return DelayNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<PannerNode>
|
||||
AudioContext::CreatePanner(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PannerNode> pannerNode = new PannerNode(this);
|
||||
mPannerNodes.PutEntry(pannerNode);
|
||||
return pannerNode.forget();
|
||||
return PannerNode::Create(*this, PannerOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<ConvolverNode>
|
||||
AudioContext::CreateConvolver(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ConvolverNode> convolverNode = new ConvolverNode(this);
|
||||
return convolverNode.forget();
|
||||
return ConvolverNode::Create(nullptr, *this, ConvolverOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<ChannelSplitterNode>
|
||||
AudioContext::CreateChannelSplitter(uint32_t aNumberOfOutputs, ErrorResult& aRv)
|
||||
{
|
||||
if (aNumberOfOutputs == 0 ||
|
||||
aNumberOfOutputs > WebAudioUtils::MaxChannelCount) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ChannelSplitterNode> splitterNode =
|
||||
new ChannelSplitterNode(this, aNumberOfOutputs);
|
||||
return splitterNode.forget();
|
||||
ChannelSplitterOptions options;
|
||||
options.mNumberOfOutputs = aNumberOfOutputs;
|
||||
return ChannelSplitterNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<ChannelMergerNode>
|
||||
AudioContext::CreateChannelMerger(uint32_t aNumberOfInputs, ErrorResult& aRv)
|
||||
{
|
||||
if (aNumberOfInputs == 0 ||
|
||||
aNumberOfInputs > WebAudioUtils::MaxChannelCount) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ChannelMergerNode> mergerNode =
|
||||
new ChannelMergerNode(this, aNumberOfInputs);
|
||||
return mergerNode.forget();
|
||||
ChannelMergerOptions options;
|
||||
options.mNumberOfInputs = aNumberOfInputs;
|
||||
return ChannelMergerNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<DynamicsCompressorNode>
|
||||
AudioContext::CreateDynamicsCompressor(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DynamicsCompressorNode> compressorNode =
|
||||
new DynamicsCompressorNode(this);
|
||||
return compressorNode.forget();
|
||||
return DynamicsCompressorNode::Create(*this, DynamicsCompressorOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<BiquadFilterNode>
|
||||
AudioContext::CreateBiquadFilter(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BiquadFilterNode> filterNode =
|
||||
new BiquadFilterNode(this);
|
||||
return filterNode.forget();
|
||||
return BiquadFilterNode::Create(*this, BiquadFilterOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IIRFilterNode>
|
||||
@@ -526,47 +440,16 @@ AudioContext::CreateIIRFilter(const mozilla::dom::binding_detail::AutoSequence<d
|
||||
const mozilla::dom::binding_detail::AutoSequence<double>& aFeedback,
|
||||
mozilla::ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aFeedforward.Length() == 0 || aFeedforward.Length() > 20) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aFeedback.Length() == 0 || aFeedback.Length() > 20) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool feedforwardAllZeros = true;
|
||||
for (size_t i = 0; i < aFeedforward.Length(); ++i) {
|
||||
if (aFeedforward.Elements()[i] != 0.0) {
|
||||
feedforwardAllZeros = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (feedforwardAllZeros || aFeedback.Elements()[0] == 0.0) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IIRFilterNode> filterNode =
|
||||
new IIRFilterNode(this, aFeedforward, aFeedback);
|
||||
return filterNode.forget();
|
||||
IIRFilterOptions options;
|
||||
options.mFeedforward = aFeedforward;
|
||||
options.mFeedback = aFeedback;
|
||||
return IIRFilterNode::Create(*this, options, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<OscillatorNode>
|
||||
AudioContext::CreateOscillator(ErrorResult& aRv)
|
||||
{
|
||||
if (CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<OscillatorNode> oscillatorNode =
|
||||
new OscillatorNode(this);
|
||||
return oscillatorNode.forget();
|
||||
return OscillatorNode::Create(*this, OscillatorOptions(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<PeriodicWave>
|
||||
|
||||
@@ -316,6 +316,8 @@ public:
|
||||
IMPL_EVENT_HANDLER(mozinterruptbegin)
|
||||
IMPL_EVENT_HANDLER(mozinterruptend)
|
||||
|
||||
bool CheckClosed(ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
void DisconnectFromWindow();
|
||||
void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
|
||||
@@ -326,8 +328,6 @@ private:
|
||||
|
||||
friend struct ::mozilla::WebAudioDecodeJob;
|
||||
|
||||
bool CheckClosed(ErrorResult& aRv);
|
||||
|
||||
nsTArray<MediaStream*> GetAllStreams() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -71,6 +71,28 @@ AudioNode::~AudioNode()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Initialize(const AudioNodeOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
if (aOptions.mChannelCount.WasPassed()) {
|
||||
SetChannelCount(aOptions.mChannelCount.Value(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aOptions.mChannelCountMode.WasPassed()) {
|
||||
SetChannelCountModeValue(aOptions.mChannelCountMode.Value(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aOptions.mChannelInterpretation.WasPassed()) {
|
||||
SetChannelInterpretationValue(aOptions.mChannelInterpretation.Value());
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
|
||||
@@ -250,6 +250,9 @@ private:
|
||||
bool DisconnectFromOutputIfConnected(uint32_t aOutputIndex, uint32_t aInputIndex);
|
||||
|
||||
protected:
|
||||
// Helper for the Constructors for nodes.
|
||||
void Initialize(const AudioNodeOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
// Helpers for sending different value types to streams
|
||||
void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
|
||||
void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue);
|
||||
|
||||
@@ -262,8 +262,29 @@ BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
|
||||
aContext->Graph());
|
||||
}
|
||||
|
||||
BiquadFilterNode::~BiquadFilterNode()
|
||||
/* static */ already_AddRefed<BiquadFilterNode>
|
||||
BiquadFilterNode::Create(AudioContext& aAudioContext,
|
||||
const BiquadFilterOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BiquadFilterNode> audioNode = new BiquadFilterNode(&aAudioContext);
|
||||
|
||||
audioNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
audioNode->SetType(aOptions.mType);
|
||||
audioNode->Q()->SetValue(aOptions.mQ);
|
||||
audioNode->Detune()->SetValue(aOptions.mDetune);
|
||||
audioNode->Frequency()->SetValue(aOptions.mFrequency);
|
||||
audioNode->Gain()->SetValue(aOptions.mGain);
|
||||
|
||||
return audioNode.forget();
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -14,15 +14,25 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct BiquadFilterOptions;
|
||||
|
||||
class BiquadFilterNode final : public AudioNode
|
||||
{
|
||||
public:
|
||||
explicit BiquadFilterNode(AudioContext* aContext);
|
||||
static already_AddRefed<BiquadFilterNode>
|
||||
Create(AudioContext& aAudioContext, const BiquadFilterOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BiquadFilterNode, AudioNode)
|
||||
|
||||
static already_AddRefed<BiquadFilterNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const BiquadFilterOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
BiquadFilterType Type() const
|
||||
@@ -63,10 +73,10 @@ public:
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
protected:
|
||||
virtual ~BiquadFilterNode();
|
||||
|
||||
private:
|
||||
explicit BiquadFilterNode(AudioContext* aContext);
|
||||
~BiquadFilterNode() = default;
|
||||
|
||||
BiquadFilterType mType;
|
||||
RefPtr<AudioParam> mFrequency;
|
||||
RefPtr<AudioParam> mDetune;
|
||||
@@ -78,4 +88,3 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -74,8 +74,30 @@ ChannelMergerNode::ChannelMergerNode(AudioContext* aContext,
|
||||
aContext->Graph());
|
||||
}
|
||||
|
||||
ChannelMergerNode::~ChannelMergerNode()
|
||||
/* static */ already_AddRefed<ChannelMergerNode>
|
||||
ChannelMergerNode::Create(AudioContext& aAudioContext,
|
||||
const ChannelMergerOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOptions.mNumberOfInputs == 0 ||
|
||||
aOptions.mNumberOfInputs > WebAudioUtils::MaxChannelCount) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ChannelMergerNode> audioNode =
|
||||
new ChannelMergerNode(&aAudioContext, aOptions.mNumberOfInputs);
|
||||
|
||||
audioNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return audioNode.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@@ -86,4 +108,3 @@ ChannelMergerNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -12,15 +12,24 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct ChannelMergerOptions;
|
||||
|
||||
class ChannelMergerNode final : public AudioNode
|
||||
{
|
||||
public:
|
||||
ChannelMergerNode(AudioContext* aContext,
|
||||
uint16_t aInputCount);
|
||||
static already_AddRefed<ChannelMergerNode>
|
||||
Create(AudioContext& aAudioContext, const ChannelMergerOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
static already_AddRefed<ChannelMergerNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const ChannelMergerOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
uint16_t NumberOfInputs() const override { return mInputCount; }
|
||||
@@ -35,10 +44,11 @@ public:
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~ChannelMergerNode();
|
||||
|
||||
private:
|
||||
ChannelMergerNode(AudioContext* aContext,
|
||||
uint16_t aInputCount);
|
||||
~ChannelMergerNode() = default;
|
||||
|
||||
const uint16_t mInputCount;
|
||||
};
|
||||
|
||||
@@ -46,4 +56,3 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,8 +65,30 @@ ChannelSplitterNode::ChannelSplitterNode(AudioContext* aContext,
|
||||
aContext->Graph());
|
||||
}
|
||||
|
||||
ChannelSplitterNode::~ChannelSplitterNode()
|
||||
/* static */ already_AddRefed<ChannelSplitterNode>
|
||||
ChannelSplitterNode::Create(AudioContext& aAudioContext,
|
||||
const ChannelSplitterOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOptions.mNumberOfOutputs == 0 ||
|
||||
aOptions.mNumberOfOutputs > WebAudioUtils::MaxChannelCount) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ChannelSplitterNode> audioNode =
|
||||
new ChannelSplitterNode(&aAudioContext, aOptions.mNumberOfOutputs);
|
||||
|
||||
audioNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return audioNode.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@@ -77,4 +99,3 @@ ChannelSplitterNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProt
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -12,15 +12,24 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct ChannelSplitterOptions;
|
||||
|
||||
class ChannelSplitterNode final : public AudioNode
|
||||
{
|
||||
public:
|
||||
ChannelSplitterNode(AudioContext* aContext,
|
||||
uint16_t aOutputCount);
|
||||
static already_AddRefed<ChannelSplitterNode>
|
||||
Create(AudioContext& aAudioContext, const ChannelSplitterOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
static already_AddRefed<ChannelSplitterNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const ChannelSplitterOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
uint16_t NumberOfOutputs() const override { return mOutputCount; }
|
||||
@@ -35,10 +44,11 @@ public:
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~ChannelSplitterNode();
|
||||
|
||||
private:
|
||||
ChannelSplitterNode(AudioContext* aContext,
|
||||
uint16_t aOutputCount);
|
||||
~ChannelSplitterNode() = default;
|
||||
|
||||
const uint16_t mOutputCount;
|
||||
};
|
||||
|
||||
@@ -46,4 +56,3 @@ private:
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -203,8 +203,34 @@ ConvolverNode::ConvolverNode(AudioContext* aContext)
|
||||
aContext->Graph());
|
||||
}
|
||||
|
||||
ConvolverNode::~ConvolverNode()
|
||||
/* static */ already_AddRefed<ConvolverNode>
|
||||
ConvolverNode::Create(JSContext* aCx, AudioContext& aAudioContext,
|
||||
const ConvolverOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ConvolverNode> audioNode = new ConvolverNode(&aAudioContext);
|
||||
|
||||
audioNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This must be done before setting the buffer.
|
||||
audioNode->SetNormalize(!aOptions.mDisableNormalization);
|
||||
|
||||
if (aOptions.mBuffer.WasPassed()) {
|
||||
MOZ_ASSERT(aCx);
|
||||
audioNode->SetBuffer(aCx, aOptions.mBuffer.Value(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return audioNode.forget();
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -291,4 +317,3 @@ ConvolverNode::SetNormalize(bool aNormalize)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -12,14 +12,26 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct ConvolverOptions;
|
||||
|
||||
class ConvolverNode final : public AudioNode
|
||||
{
|
||||
public:
|
||||
explicit ConvolverNode(AudioContext* aContext);
|
||||
static already_AddRefed<ConvolverNode>
|
||||
Create(JSContext* aCx, AudioContext& aAudioContext,
|
||||
const ConvolverOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ConvolverNode, AudioNode);
|
||||
|
||||
static already_AddRefed<ConvolverNode>
|
||||
Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
|
||||
const ConvolverOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
return Create(aGlobal.Context(), aAudioContext, aOptions, aRv);
|
||||
}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
AudioBuffer* GetBuffer(JSContext* aCx) const
|
||||
@@ -27,7 +39,7 @@ public:
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
void SetBuffer(JSContext* aCx, AudioBuffer* aBufferi, ErrorResult& aRv);
|
||||
void SetBuffer(JSContext* aCx, AudioBuffer* aBuffer, ErrorResult& aRv);
|
||||
|
||||
bool Normalize() const
|
||||
{
|
||||
@@ -61,10 +73,10 @@ public:
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
protected:
|
||||
virtual ~ConvolverNode();
|
||||
|
||||
private:
|
||||
explicit ConvolverNode(AudioContext* aContext);
|
||||
~ConvolverNode() = default;
|
||||
|
||||
RefPtr<AudioBuffer> mBuffer;
|
||||
bool mNormalize;
|
||||
};
|
||||
@@ -74,4 +86,3 @@ private:
|
||||
} //end namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -205,8 +205,30 @@ DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
|
||||
aContext->Graph());
|
||||
}
|
||||
|
||||
DelayNode::~DelayNode()
|
||||
/* static */ already_AddRefed<DelayNode>
|
||||
DelayNode::Create(AudioContext& aAudioContext,
|
||||
const DelayOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aAudioContext.CheckClosed(aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOptions.mMaxDelayTime <= 0. || aOptions.mMaxDelayTime >= 180.) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DelayNode> audioNode = new DelayNode(&aAudioContext,
|
||||
aOptions.mMaxDelayTime);
|
||||
|
||||
audioNode->Initialize(aOptions, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
audioNode->DelayTime()->SetValue(aOptions.mDelayTime);
|
||||
return audioNode.forget();
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
Loaded 100 of 2737 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user