mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-11 10:08:41 +00:00
Bug 68871. Permit partial sharing of XUL attributes, remove unused fields from nsXULElement and nsXULElement::Slots. Tag teamed with shaver@mozilla.org, r=shaver; sr=hyatt.
This commit is contained in:
parent
c8469b7ac5
commit
a34851ef20
@ -113,13 +113,6 @@ public:
|
||||
* Add a script event listener to the element.
|
||||
*/
|
||||
NS_IMETHOD AddScriptEventListener(nsIAtom* aName, const nsAReadableString& aValue) = 0;
|
||||
|
||||
/**
|
||||
* Evil rotten hack to make mailnews work. They assume that we
|
||||
* keep a reference to their resource objects. If you think you
|
||||
* should call this method, think again. You shouldn't.
|
||||
*/
|
||||
NS_IMETHOD ForceElementToOwnResource(PRBool aForce) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIXULContent_h__
|
||||
|
@ -22,7 +22,6 @@
|
||||
* Contributor(s):
|
||||
* Edward Kandrot <kandrot@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
@ -63,7 +62,7 @@ public:
|
||||
nsXULAttributeValue();
|
||||
~nsXULAttributeValue();
|
||||
|
||||
void ReleaseValue( void );
|
||||
void ReleaseValue();
|
||||
|
||||
nsresult GetValue(nsAWritableString& aResult);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
* Peter Annema <disttsc@bart.nl>
|
||||
*
|
||||
* Mike Shaver <shaver@mozilla.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -355,14 +355,13 @@ public:
|
||||
static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
|
||||
|
||||
protected:
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
// pseudo-constants
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static PRInt32 kNameSpaceID_RDF;
|
||||
static PRInt32 kNameSpaceID_XUL;
|
||||
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument,
|
||||
@ -449,7 +448,6 @@ public:
|
||||
NS_IMETHOD ClearLazyState(PRInt32 aFlags);
|
||||
NS_IMETHOD GetLazyState(PRInt32 aFlag, PRBool& aValue);
|
||||
NS_IMETHOD AddScriptEventListener(nsIAtom* aName, const nsAReadableString& aValue);
|
||||
NS_IMETHOD ForceElementToOwnResource(PRBool aForce);
|
||||
|
||||
// nsIDOMNode (from nsIDOMElement)
|
||||
NS_DECL_NSIDOMNODE
|
||||
@ -529,16 +527,23 @@ protected:
|
||||
nsIContent* mParent; // [WEAK]
|
||||
nsCheapVoidArray mChildren; // [OWNER]
|
||||
nsCOMPtr<nsIEventListenerManager> mListenerManager; // [OWNER]
|
||||
#ifdef DEBUG
|
||||
PRBool mIsScriptObjectRooted;
|
||||
#endif
|
||||
|
||||
// The nearest enclosing content node with a binding
|
||||
// that created us. [Weak]
|
||||
/**
|
||||
* The state of our sloth for lazy content model construction via
|
||||
* RDF; see nsIXULContent and nsRDFGenericBuilder.
|
||||
*/
|
||||
PRInt32 mLazyState;
|
||||
|
||||
/**
|
||||
* The nearest enclosing content node with a binding
|
||||
* that created us. [Weak]
|
||||
*/
|
||||
nsIContent* mBindingParent;
|
||||
|
||||
// Lazily instantiated if/when object is mutated. Instantiating
|
||||
// the mSlots makes an nsXULElement 'heavyweight'.
|
||||
/**
|
||||
* Lazily instantiated if/when object is mutated. mAttributes are
|
||||
* lazily copied from the prototype when changed.
|
||||
*/
|
||||
struct Slots {
|
||||
Slots(nsXULElement* mElement);
|
||||
~Slots();
|
||||
@ -547,24 +552,73 @@ protected:
|
||||
nsCOMPtr<nsINameSpace> mNameSpace; // [OWNER]
|
||||
nsCOMPtr<nsINodeInfo> mNodeInfo; // [OWNER]
|
||||
nsVoidArray* mBroadcastListeners; // [WEAK]
|
||||
nsIDOMXULElement* mBroadcaster; // [WEAK]
|
||||
nsCOMPtr<nsIControllers> mControllers; // [OWNER]
|
||||
nsCOMPtr<nsIRDFResource> mOwnedResource; // [OWNER]
|
||||
|
||||
/**
|
||||
* Attribute values that override the values from the prototype.
|
||||
*/
|
||||
nsXULAttributes* mAttributes;
|
||||
|
||||
// The state of our sloth for lazy content model construction via
|
||||
// RDF; see nsIXULContent and nsRDFGenericBuilder.
|
||||
/**
|
||||
* The state of our sloth for lazy content model construction via
|
||||
* RDF; see nsIXULContent and nsRDFGenericBuilder.
|
||||
*/
|
||||
PRInt32 mLazyState;
|
||||
|
||||
// An unreferenced bare pointer to an aggregate that can
|
||||
// implement element-specific APIs.
|
||||
/**
|
||||
* An unreferenced bare pointer to an aggregate that can
|
||||
* implement element-specific APIs.
|
||||
*/
|
||||
nsXULAggregateElement* mInnerXULElement;
|
||||
};
|
||||
|
||||
friend struct Slots;
|
||||
Slots* mSlots;
|
||||
|
||||
/**
|
||||
* Ensure that we've got an mSlots object, creating a Slots object
|
||||
* if necessary.
|
||||
*/
|
||||
nsresult EnsureSlots();
|
||||
|
||||
/**
|
||||
* Ensure that our mSlots has an mAttributes, creating an
|
||||
* nsXULAttributes object if necessary.
|
||||
*/
|
||||
nsresult EnsureAttributes();
|
||||
|
||||
/**
|
||||
* Abandon our prototype linkage, and copy all attributes locally
|
||||
*/
|
||||
nsresult MakeHeavyweight();
|
||||
|
||||
/**
|
||||
* Return our private copy of the attribute, if one exists.
|
||||
*/
|
||||
nsXULAttribute *FindLocalAttribute(nsINodeInfo *info) const;
|
||||
|
||||
/**
|
||||
* Return our private copy of the attribute, if one exists.
|
||||
*/
|
||||
nsXULAttribute *FindLocalAttribute(PRInt32 aNameSpaceID,
|
||||
nsIAtom *aName,
|
||||
PRInt32 *aIndex = nsnull) const;
|
||||
|
||||
/**
|
||||
* Return our prototype's attribute, if one exists.
|
||||
*/
|
||||
nsXULPrototypeAttribute *FindPrototypeAttribute(nsINodeInfo *info) const;
|
||||
|
||||
/**
|
||||
* Return our prototype's attribute, if one exists.
|
||||
*/
|
||||
nsXULPrototypeAttribute *FindPrototypeAttribute(PRInt32 aNameSpaceID,
|
||||
nsIAtom *aName) const;
|
||||
/**
|
||||
* Add a listener for the specified attribute, if appropriate.
|
||||
*/
|
||||
nsresult AddListenerFor(nsINodeInfo *aNodeInfo,
|
||||
PRBool aCompileEventHandlers);
|
||||
|
||||
protected:
|
||||
// Internal accessors. These shadow the 'Slots', and return
|
||||
@ -573,9 +627,7 @@ protected:
|
||||
nsINameSpace* NameSpace() const { return mSlots ? mSlots->mNameSpace.get() : mPrototype->mNameSpace.get(); }
|
||||
nsINodeInfo* NodeInfo() const { return mSlots ? mSlots->mNodeInfo : mPrototype->mNodeInfo; }
|
||||
nsVoidArray* BroadcastListeners() const { return mSlots ? mSlots->mBroadcastListeners : nsnull; }
|
||||
nsIDOMXULElement* Broadcaster() const { return mSlots ? mSlots->mBroadcaster : nsnull; }
|
||||
nsIControllers* Controllers() const { return mSlots ? mSlots->mControllers.get() : nsnull; }
|
||||
nsIRDFResource* OwnedResource() const { return mSlots ? mSlots->mOwnedResource.get() : nsnull; }
|
||||
nsXULAttributes* Attributes() const { return mSlots ? mSlots->mAttributes : nsnull; }
|
||||
nsXULAggregateElement* InnerXULElement() const { return mSlots ? mSlots->mInnerXULElement : nsnull; }
|
||||
|
||||
|
@ -1235,12 +1235,9 @@ nsXULDocument::AddStyleSheet(nsIStyleSheet* aSheet)
|
||||
AddStyleSheetToStyleSets(aSheet);
|
||||
|
||||
// XXX should observers be notified for disabled sheets??? I think not, but I could be wrong
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(i);
|
||||
observer->StyleSheetAdded(this, aSheet);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1302,12 +1299,9 @@ nsXULDocument::UpdateStyleSheets(nsISupportsArray* aOldSheets, nsISupportsArray*
|
||||
}
|
||||
}
|
||||
|
||||
for (PRInt32 indx = 0; indx < mObservers.Count(); indx++) {
|
||||
for (PRInt32 indx = mObservers.Count() - 1; indx >= 0; --indx) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(indx);
|
||||
observer->StyleSheetRemoved(this, sheet);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(indx)) {
|
||||
indx--;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1342,12 +1336,9 @@ nsXULDocument::RemoveStyleSheet(nsIStyleSheet* aSheet)
|
||||
RemoveStyleSheetFromStyleSets(aSheet);
|
||||
|
||||
// XXX should observers be notified for disabled sheets??? I think not, but I could be wrong
|
||||
for (PRInt32 indx = 0; indx < mObservers.Count(); indx++) {
|
||||
for (PRInt32 indx = mObservers.Count() - 1; indx >= 0; --indx) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(indx);
|
||||
observer->StyleSheetRemoved(this, aSheet);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(indx)) {
|
||||
indx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1382,12 +1373,9 @@ nsXULDocument::InsertStyleSheetAt(nsIStyleSheet* aSheet, PRInt32 aIndex, PRBool
|
||||
}
|
||||
}
|
||||
if (aNotify) { // notify here even if disabled, there may have been others that weren't notified
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(i);
|
||||
observer->StyleSheetAdded(this, aSheet);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1420,12 +1408,9 @@ nsXULDocument::SetStyleSheetDisabledState(nsIStyleSheet* aSheet,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers.ElementAt(i);
|
||||
observer->StyleSheetDisabledStateChanged(this, aSheet, aDisabled);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1565,12 +1550,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::BeginUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1579,12 +1561,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::EndUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1593,12 +1572,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::BeginLoad()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginLoad(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1714,12 +1690,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::ContentChanged(nsIContent* aContent,
|
||||
nsISupports* aSubContent)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentChanged(this, aContent, aSubContent);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1727,12 +1700,9 @@ nsXULDocument::ContentChanged(nsIContent* aContent,
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentStatesChanged(this, aContent1, aContent2);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1763,12 +1733,9 @@ nsXULDocument::AttributeChanged(nsIContent* aElement,
|
||||
}
|
||||
|
||||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->AttributeChanged(this, aElement, aNameSpaceID, aAttribute, aModType, aHint);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, see if there is anything we need to persist in the
|
||||
@ -1816,12 +1783,9 @@ nsXULDocument::ContentAppended(nsIContent* aContainer,
|
||||
}
|
||||
|
||||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentAppended(this, aContainer, aNewIndexInContainer);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1838,12 +1802,9 @@ nsXULDocument::ContentInserted(nsIContent* aContainer,
|
||||
}
|
||||
|
||||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentInserted(this, aContainer, aChild, aIndexInContainer);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1864,13 +1825,10 @@ nsXULDocument::ContentReplaced(nsIContent* aContainer,
|
||||
}
|
||||
|
||||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentReplaced(this, aContainer, aOldChild, aNewChild,
|
||||
aIndexInContainer);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1887,13 +1845,10 @@ nsXULDocument::ContentRemoved(nsIContent* aContainer,
|
||||
}
|
||||
|
||||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->ContentRemoved(this, aContainer,
|
||||
aChild, aIndexInContainer);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1911,12 +1866,9 @@ nsXULDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->StyleRuleChanged(this, aStyleSheet, aStyleRule, aHint);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1925,12 +1877,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::StyleRuleAdded(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->StyleRuleAdded(this, aStyleSheet, aStyleRule);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1939,12 +1888,9 @@ NS_IMETHODIMP
|
||||
nsXULDocument::StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->StyleRuleRemoved(this, aStyleSheet, aStyleRule);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -5636,12 +5582,9 @@ nsXULDocument::ResumeWalk()
|
||||
// do this after StartLayout() in case we want to serialize frames.
|
||||
EndFastLoad();
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndLoad(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the placeholder channel; if we're the last channel in the
|
||||
|
@ -655,17 +655,6 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Hackery to ensure that mailnews works. Force the
|
||||
// element to hold a reference to the
|
||||
// resource. Unfortunately, this'll break for HTML
|
||||
// elements.
|
||||
{
|
||||
nsCOMPtr<nsIXULContent> xulele = do_QueryInterface(realKid);
|
||||
if (xulele) {
|
||||
xulele->ForceElementToOwnResource(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the element's 'container' and 'empty'
|
||||
// attributes.
|
||||
PRBool iscontainer, isempty;
|
||||
|
Loading…
x
Reference in New Issue
Block a user