Back out changeset fc4ddddf142d and changeset d1766aec3d7e due to jsreftest orange.

This commit is contained in:
Henri Sivonen 2011-10-30 00:10:33 +03:00
parent 1c978c415e
commit df4d9f2647
13 changed files with 56 additions and 159 deletions

View File

@ -77,13 +77,6 @@ nsHtml5OwningUTF16Buffer::FalliblyCreate(PRInt32 aLength)
return newObj.forget();
}
void
nsHtml5OwningUTF16Buffer::Swap(nsHtml5OwningUTF16Buffer* aOther)
{
nsHtml5UTF16Buffer::Swap(aOther);
}
// Not using macros for AddRef and Release in order to be able to refcount on
// and create on different threads.

View File

@ -75,11 +75,6 @@ class nsHtml5OwningUTF16Buffer : public nsHtml5UTF16Buffer
static already_AddRefed<nsHtml5OwningUTF16Buffer>
FalliblyCreate(PRInt32 aLength);
/**
* Swap start, end and buffer fields with another object.
*/
void Swap(nsHtml5OwningUTF16Buffer* aOther);
nsrefcnt AddRef();
nsrefcnt Release();
private:

View File

@ -287,103 +287,25 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
NS_ASSERTION(!mStreamParser,
"Had stream parser but got document.close().");
mDocumentClosed = true;
if (!mBlocked && !mInDocumentWrite) {
if (!mBlocked) {
ParseUntilBlocked();
}
return NS_OK;
}
// If we got this far, we are dealing with a document.write or
// document.writeln call--not document.close().
NS_ASSERTION(IsInsertionPointDefined(),
"Doc.write reached parser with undefined insertion point.");
NS_ASSERTION(!(mStreamParser && !aKey),
"Got a null key in a non-script-created parser");
// XXX is this optimization bogus?
if (aSourceBuffer.IsEmpty()) {
return NS_OK;
}
// This guard is here to prevent document.close from tokenizing synchronously
// while a document.write (that wrote the script that called document.close!)
// is still on the call stack.
mozilla::AutoRestore<bool> guard(mInDocumentWrite);
mInDocumentWrite = true;
// The script is identified by aKey. If there's nothing in the buffer
// chain for that key, we'll insert at the head of the queue.
// When the script leaves something in the queue, a zero-length
// key-holder "buffer" is inserted in the queue. If the same script
// leaves something in the chain again, it will be inserted immediately
// before the old key holder belonging to the same script.
//
// We don't do the actual data insertion yet in the hope that the data gets
// tokenized and there no data or less data to copy to the heap after
// tokenization. Also, this way, we avoid inserting one empty data buffer
// per document.write, which matters for performance when the parser isn't
// blocked and a badly-authored script calls document.write() once per
// input character. (As seen in a benchmark!)
//
// The insertion into the input stream happens conceptually before anything
// gets tokenized. To make sure multi-level document.write works right,
// it's necessary to establish the location of our parser key up front
// in case this is the first write with this key.
//
// In a document.open() case, the first write level has a null key, so that
// case is handled separately, because normal buffers containing data
// have null keys.
nsHtml5OwningUTF16Buffer* prevSearchBuf = nsnull;
nsHtml5OwningUTF16Buffer* firstLevelMarker = nsnull;
if (aKey) {
if (mFirstBuffer == mLastBuffer) {
nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
keyHolder->next = mLastBuffer;
mFirstBuffer = keyHolder;
} else {
prevSearchBuf = mFirstBuffer;
for (;;) {
if (prevSearchBuf->next == mLastBuffer) {
// key was not found
nsHtml5OwningUTF16Buffer* keyHolder =
new nsHtml5OwningUTF16Buffer(aKey);
keyHolder->next = mFirstBuffer;
mFirstBuffer = keyHolder;
prevSearchBuf = nsnull;
break;
}
if (prevSearchBuf->next->key == aKey) {
// found a key holder
break;
}
prevSearchBuf = prevSearchBuf->next;
}
}
// prevSearchBuf is the previous buffer before the keyholder or null if
// there isn't one.
} else {
// We have a first-level write in the document.open() case. We insert
// before mLastBuffer. We need to put a marker there, because otherwise
// additional document.writes from nested event loops would insert in the
// wrong place. Sigh.
firstLevelMarker = new nsHtml5OwningUTF16Buffer((void*)nsnull);
if (mFirstBuffer == mLastBuffer) {
firstLevelMarker->next = mLastBuffer;
mFirstBuffer = firstLevelMarker;
} else {
prevSearchBuf = mFirstBuffer;
while (prevSearchBuf->next != mLastBuffer) {
prevSearchBuf = prevSearchBuf->next;
}
firstLevelMarker->next = mLastBuffer;
prevSearchBuf->next = firstLevelMarker;
}
}
nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);
while (!mBlocked && stackBuffer.hasMore()) {
@ -433,35 +355,60 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
}
}
if (heapBuffer) {
// We have something to insert before the keyholder holding in the non-null
// aKey case and we have something to swap into firstLevelMarker in the
// null aKey case.
if (aKey) {
NS_ASSERTION(mFirstBuffer != mLastBuffer,
"Where's the keyholder?");
// the key holder is still somewhere further down the list from
// prevSearchBuf (which may be null)
if (mFirstBuffer->key == aKey) {
NS_ASSERTION(!prevSearchBuf,
"Non-null prevSearchBuf when mFirstBuffer is the key holder?");
heapBuffer->next = mFirstBuffer;
// The buffer is inserted to the stream here in case it won't be parsed
// to completion.
// The script is identified by aKey. If there's nothing in the buffer
// chain for that key, we'll insert at the head of the queue.
// When the script leaves something in the queue, a zero-length
// key-holder "buffer" is inserted in the queue. If the same script
// leaves something in the chain again, it will be inserted immediately
// before the old key holder belonging to the same script.
nsHtml5OwningUTF16Buffer* prevSearchBuf = nsnull;
nsHtml5OwningUTF16Buffer* searchBuf = mFirstBuffer;
// after document.open, the first level of document.write has null key
if (aKey) {
while (searchBuf != mLastBuffer) {
if (searchBuf->key == aKey) {
// found a key holder
// now insert the new buffer between the previous buffer
// and the key holder if we have a buffer left.
if (heapBuffer) {
heapBuffer->next = searchBuf;
if (prevSearchBuf) {
prevSearchBuf->next = heapBuffer;
} else {
mFirstBuffer = heapBuffer;
}
}
break;
}
prevSearchBuf = searchBuf;
searchBuf = searchBuf->next;
}
if (searchBuf == mLastBuffer) {
// key was not found
nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
keyHolder->next = mFirstBuffer;
if (heapBuffer) {
heapBuffer->next = keyHolder;
mFirstBuffer = heapBuffer;
} else {
if (!prevSearchBuf) {
prevSearchBuf = mFirstBuffer;
}
// We created a key holder earlier, so we will find it without walking
// past the end of the list.
while (prevSearchBuf->next->key != aKey) {
prevSearchBuf = prevSearchBuf->next;
}
heapBuffer->next = prevSearchBuf->next;
prevSearchBuf->next = heapBuffer;
mFirstBuffer = keyHolder;
}
}
} else if (heapBuffer) {
// we have a first level document.write after document.open()
// insert immediately before mLastBuffer
while (searchBuf != mLastBuffer) {
prevSearchBuf = searchBuf;
searchBuf = searchBuf->next;
}
heapBuffer->next = mLastBuffer;
if (prevSearchBuf) {
prevSearchBuf->next = heapBuffer;
} else {
NS_ASSERTION(firstLevelMarker, "How come we don't have a marker.");
firstLevelMarker->Swap(heapBuffer);
mFirstBuffer = heapBuffer;
}
}
@ -710,12 +657,14 @@ nsHtml5Parser::ParseUntilBlocked()
NS_PRECONDITION(!mExecutor->IsFragmentMode(),
"ParseUntilBlocked called in fragment mode.");
if (mBlocked || mExecutor->IsComplete() || mExecutor->IsBroken()) {
if (mBlocked ||
mExecutor->IsComplete() ||
mExecutor->IsBroken() ||
mInDocumentWrite) {
return;
}
NS_ASSERTION(mExecutor->HasStarted(), "Bad life cycle.");
NS_ASSERTION(!mInDocumentWrite,
"ParseUntilBlocked entered while in doc.write!");
mDocWriteSpeculatorActive = false;

View File

@ -53,17 +53,3 @@ nsHtml5UTF16Buffer::DeleteBuffer()
{
delete[] buffer;
}
void
nsHtml5UTF16Buffer::Swap(nsHtml5UTF16Buffer* aOther)
{
PRUnichar* tempBuffer = buffer;
PRInt32 tempStart = start;
PRInt32 tempEnd = end;
buffer = aOther->buffer;
start = aOther->start;
end = aOther->end;
aOther->buffer = tempBuffer;
aOther->start = tempStart;
aOther->end = tempEnd;
}

View File

@ -43,8 +43,3 @@ protected:
* For working around the privacy of |buffer| in the generated code.
*/
void DeleteBuffer();
/**
* For working around the privacy of |buffer| in the generated code.
*/
void Swap(nsHtml5UTF16Buffer* aOther);

View File

@ -1 +0,0 @@
<!DOCTYPE html>CcBbAa

View File

@ -1,2 +0,0 @@
<!DOCTYPE html>
<body><script>document.write("\u003cscript>document.write(\"\\u003cscript src='bug696651-external.js'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); document.write("a");</script>

View File

@ -1,2 +0,0 @@
<!DOCTYPE html>
<body><script>document.write("\u003cscript>document.write(\"\\u003cscript src='data:text/javascript,document.write(%27C%27);%20document.write(%27c%27);'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); document.write("a");</script>

View File

@ -1 +0,0 @@
<!DOCTYPE html><iframe src="data:text/html,<!DOCTYPE html>CcBbAa"></iframe>

View File

@ -1,6 +0,0 @@
<!DOCTYPE html>
<body>
<iframe></iframe>
<script>
var doc = document.getElementsByTagName("iframe")[0].contentDocument;
doc.open(); doc.write("\u003cscript>document.write(\"\\u003cscript src='bug696651-external.js'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); doc.write("a"); doc.close();</script>

View File

@ -1,6 +0,0 @@
<!DOCTYPE html>
<body>
<iframe></iframe>
<script>
var doc = document.getElementsByTagName("iframe")[0].contentDocument;
doc.open(); doc.write("\u003cscript>document.write(\"\\u003cscript src='data:text/javascript,document.write(%27C%27);%20document.write(%27c%27);'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); doc.write("a"); doc.close();</script>

View File

@ -1 +0,0 @@
document.write("C"); document.write("c");

View File

@ -5,5 +5,3 @@
== bug592656-1.html bug592656-1-ref.html
== bug608373-1.html bug608373-1-ref.html
== view-source:bug673094-1.html view-source:bug673094-1-ref.html
== bug696651-1.html bug696651-1-ref.html
== bug696651-2.html bug696651-2-ref.html