Bug 453736. Make <svg:script> more like other scripts and fix up a few other minor issues. r=roc, r+sr=sicking

This commit is contained in:
Boris Zbarsky 2009-01-14 07:49:18 -05:00
parent 4189af9d67
commit 00e66d09cf
7 changed files with 146 additions and 18 deletions

View File

@ -177,8 +177,13 @@ nsScriptElement::MaybeProcessScript()
"You forgot to add self as observer");
if (mIsEvaluated || !mDoneAddingChildren || !cont->IsInDoc() ||
mMalformed || InNonScriptingContainer(cont) ||
!HasScriptContent()) {
mMalformed || !HasScriptContent()) {
return NS_OK;
}
if (InNonScriptingContainer(cont)) {
// Make sure to flag ourselves as evaluated
mIsEvaluated = PR_TRUE;
return NS_OK;
}

View File

@ -240,6 +240,7 @@ _TEST_FILES = test_bug5141.html \
test_bug368972.html \
test_bug448993.html \
test_bug450160.html \
test_bug453736.html \
test_bug454326.html \
test_bug457746.html \
bug457746.sjs \

View File

@ -0,0 +1,97 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=453736
-->
<head>
<title>Test for Bug 453736</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=453736">Mozilla Bug 453736</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 453736 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
const scriptCreationFuncs = [
function() { return document.createElement("script"); },
function() { return document.createElementNS("http://www.w3.org/2000/svg", "script"); }
];
const noScriptContainers = ["iframe", "noframes", "noembed"];
for (var i = 0; i < noScriptContainers.length; ++i) {
for each (var func in scriptCreationFuncs) {
var cont = noScriptContainers[i];
var node = document.createElement(cont);
document.body.appendChild(node);
var s = func();
s.setAttribute("type", "application/javascript");
s.appendChild(document.createTextNode('window["'+cont+'ScriptRan"] = true'));
window[cont+"ScriptRan"] = false;
document.body.appendChild(s.cloneNode(true));
is(window[cont+"ScriptRan"], true,
"Clone of non-inserted script created with " + func +" should run");
window[cont+"ScriptRan"] = false;
node.appendChild(s);
is(window[cont+"ScriptRan"], false,
"Script created with " + func +" shouldn't run when inserting in <"+cont+">");
window[cont+"ScriptRan"] = false;
document.body.appendChild(s);
is(window[cont+"ScriptRan"], false,
"Script created with " + func + " shouldn't run when moving out of <"+cont+">");
window[cont+"ScriptRan"] = false;
document.body.appendChild(s.cloneNode(true));
is(window[cont+"ScriptRan"], false,
"Clone of script inside <" + cont + "> created with " + func + " shouldn't run");
}
}
const scriptContainers = ["div"];
for (var i = 0; i < scriptContainers.length; ++i) {
for each (var func in scriptCreationFuncs) {
var cont = scriptContainers[i];
var node = document.createElement(cont);
document.body.appendChild(node);
var s = func();
s.setAttribute("type", "application/javascript");
s.appendChild(document.createTextNode('window["'+cont+'ScriptRan"] = true'));
window[cont+"ScriptRan"] = false;
node.appendChild(s);
is(window[cont+"ScriptRan"], true,
"Script created with " + func +" should run when inserting in <"+cont+">");
window[cont+"ScriptRan"] = false;
document.body.appendChild(s);
is(window[cont+"ScriptRan"], false,
"Script created with " + func + " shouldn't run when moving out of <"+cont+">");
window[cont+"ScriptRan"] = false;
document.body.appendChild(s.cloneNode(true));
is(window[cont+"ScriptRan"], false,
"Clone of script inside <" + cont + "> created with " + func + " shouldn't run");
}
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -432,9 +432,7 @@ nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
nsresult rv = CopyInnerTo(it);
NS_ENSURE_SUCCESS(rv, rv);
// The clone should be marked evaluated if we are. It should also be marked
// evaluated if we're evaluating, to handle the case when this script node's
// script clones the node.
// The clone should be marked evaluated if we are.
it->mIsEvaluated = mIsEvaluated;
it->mLineNumber = mLineNumber;
it->mMalformed = mMalformed;

View File

@ -101,10 +101,6 @@ protected:
enum { HREF };
nsSVGString mStringAttributes[1];
static StringInfo sStringInfo[1];
PRUint32 mLineNumber;
PRPackedBool mIsEvaluated;
PRPackedBool mEvaluating;
};
nsSVGElement::StringInfo nsSVGScriptElement::sStringInfo[1] =
@ -132,10 +128,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGScriptElementBase)
// Implementation
nsSVGScriptElement::nsSVGScriptElement(nsINodeInfo *aNodeInfo)
: nsSVGScriptElementBase(aNodeInfo),
mLineNumber(0),
mIsEvaluated(PR_FALSE),
mEvaluating(PR_FALSE)
: nsSVGScriptElementBase(aNodeInfo)
{
AddMutationObserver(this);
}
@ -143,7 +136,29 @@ nsSVGScriptElement::nsSVGScriptElement(nsINodeInfo *aNodeInfo)
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGScriptElement)
nsresult
nsSVGScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
{
*aResult = nsnull;
nsSVGScriptElement* it = new nsSVGScriptElement(aNodeInfo);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsINode> kungFuDeathGrip = it;
nsresult rv = CopyInnerTo(it);
NS_ENSURE_SUCCESS(rv, rv);
// The clone should be marked evaluated if we are.
it->mIsEvaluated = mIsEvaluated;
it->mLineNumber = mLineNumber;
it->mMalformed = mMalformed;
kungFuDeathGrip.swap(*aResult);
return NS_OK;
}
//----------------------------------------------------------------------
// nsIDOMSVGScriptElement methods

View File

@ -9674,6 +9674,8 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
nsresult
nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
{
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Someone forgot a script blocker");
PRInt32 count = aChangeList.Count();
if (!count)
return NS_OK;
@ -13261,6 +13263,11 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
return;
}
nsAutoScriptBlocker scriptBlocker;
// Make sure that the viewmanager will outlive the presshell
nsIViewManager::UpdateViewBatch batch(mPresShell->GetViewManager());
// Processing the style changes could cause a flush that propagates to
// the parent frame and thus destroys the pres shell.
nsCOMPtr<nsIPresShell> kungFuDeathGrip(mPresShell);
@ -13268,8 +13275,10 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
// Tell the style set to get the old rule tree out of the way
// so we can recalculate while maintaining rule tree immutability
nsresult rv = mPresShell->StyleSet()->BeginReconstruct();
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
return;
}
// Recalculate all of the style contexts for the document
// Note that we can ignore the return value of ComputeStyleChangeFor
@ -13290,6 +13299,7 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
// reconstructed will still have their old style context pointers
// until they are destroyed).
mPresShell->StyleSet()->EndReconstruct();
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}
void
@ -13450,8 +13460,10 @@ nsCSSFrameConstructor::LazyGenerateChildrenEvent::Run()
nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
nsresult rv = fc->ProcessChildren(state, mContent, frame->GetStyleContext(),
frame, PR_FALSE, childItems, PR_FALSE);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
fc->EndUpdate();
return rv;
}
frame->SetInitialChildList(nsnull, childItems.childList);

View File

@ -164,7 +164,7 @@ public:
PRUint32 GetHoverGeneration() const { return mHoverGeneration; }
// Note: It's the caller's responsibility to make sure to wrap a
// ProcessRestyledFrames call in a view update batch.
// ProcessRestyledFrames call in a view update batch and a script blocker.
// This function does not call ProcessAttachedQueue() on the binding manager.
// If the caller wants that to happen synchronously, it needs to handle that
// itself.
@ -198,7 +198,7 @@ public:
PRInt32 aNewIndexInContainer);
// Note: It's the caller's responsibility to make sure to wrap a
// ProcessPendingRestyles call in a view update batch.
// ProcessPendingRestyles call in a view update batch and a script blocker.
// This function does not call ProcessAttachedQueue() on the binding manager.
// If the caller wants that to happen synchronously, it needs to handle that
// itself.