nsHtml5Parser::UnblockParser() { MOZ_DIAGNOSTIC_ASSERT(mBlocked > 0); if (MOZ_LIKELY(mBlocked > 0)) { mBlocked--; } if (MOZ_LIKELY(mBlocked == 0)) { mExecutor->ContinueInterruptedParsingAsync(); } }
WebGLVertexAttrib0Status WebGLContext::WhatDoesVertexAttrib0Need() { MOZ_ASSERT(mCurrentProgram); MOZ_ASSERT(mActiveProgramLinkInfo); // work around Mac OSX crash, see bug 631420 #ifdef XP_MACOSX if (gl->WorkAroundDriverBugs() && mBoundVertexArray->IsAttribArrayEnabled(0) && !mActiveProgramLinkInfo->HasActiveAttrib(0)) { return WebGLVertexAttrib0Status::EmulatedUninitializedArray; } #endif if (MOZ_LIKELY(gl->IsGLES() || mBoundVertexArray->IsAttribArrayEnabled(0))) { return WebGLVertexAttrib0Status::Default; } return mActiveProgramLinkInfo->HasActiveAttrib(0) ? WebGLVertexAttrib0Status::EmulatedInitializedArray : WebGLVertexAttrib0Status::EmulatedUninitializedArray; }
static bool ValidateBufferUsageEnum(WebGLContext* webgl, const char* funcName, GLenum usage) { switch (usage) { case LOCAL_GL_STREAM_DRAW: case LOCAL_GL_STATIC_DRAW: case LOCAL_GL_DYNAMIC_DRAW: return true; case LOCAL_GL_DYNAMIC_COPY: case LOCAL_GL_DYNAMIC_READ: case LOCAL_GL_STATIC_COPY: case LOCAL_GL_STATIC_READ: case LOCAL_GL_STREAM_COPY: case LOCAL_GL_STREAM_READ: if (MOZ_LIKELY(webgl->IsWebGL2())) return true; break; default: break; } webgl->ErrorInvalidEnum("%s: Invalid `usage`: 0x%04x", funcName, usage); return false; }
static bool ValidateBufferUsageEnum(WebGLContext* webgl, GLenum usage) { switch (usage) { case LOCAL_GL_STREAM_DRAW: case LOCAL_GL_STATIC_DRAW: case LOCAL_GL_DYNAMIC_DRAW: return true; case LOCAL_GL_DYNAMIC_COPY: case LOCAL_GL_DYNAMIC_READ: case LOCAL_GL_STATIC_COPY: case LOCAL_GL_STATIC_READ: case LOCAL_GL_STREAM_COPY: case LOCAL_GL_STREAM_READ: if (MOZ_LIKELY(webgl->IsWebGL2())) return true; break; default: break; } webgl->ErrorInvalidEnumInfo("usage", usage); return false; }
void WebGLContext::UndoFakeVertexAttrib0() { WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need(); if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)) return; if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) { const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0]; gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->mGLName); if (attrib0.integer) { gl->fVertexAttribIPointer(0, attrib0.size, attrib0.type, attrib0.stride, reinterpret_cast<const GLvoid*>(attrib0.byteOffset)); } else { gl->fVertexAttribPointer(0, attrib0.size, attrib0.type, attrib0.normalized, attrib0.stride, reinterpret_cast<const GLvoid*>(attrib0.byteOffset)); } } else { gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); } gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0); }
void Promise::ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise) { MOZ_ASSERT(!js::IsWrapper(aPromise)); MOZ_ASSERT(JS::GetPromiseState(aPromise) == JS::PromiseState::Rejected); JS::Rooted<JS::Value> result(aCx, JS::GetPromiseResult(aPromise)); js::ErrorReport report(aCx); if (!report.init(aCx, result, js::ErrorReport::NoSideEffects)) { JS_ClearPendingException(aCx); return; } RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); bool isMainThread = MOZ_LIKELY(NS_IsMainThread()); bool isChrome = isMainThread ? nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(aPromise)) : GetCurrentThreadWorkerPrivate()->IsChromeWorker(); nsGlobalWindow* win = isMainThread ? xpc::WindowGlobalOrNull(aPromise) : nullptr; xpcReport->Init(report.report(), report.toStringResult().c_str(), isChrome, win ? win->AsInner()->WindowID() : 0); // Now post an event to do the real reporting async NS_DispatchToMainThread(new AsyncErrorReporter(xpcReport)); }
bool WebGLContext::ValidateFramebufferTarget(GLenum target, const char* const info) { bool isValid = true; switch (target) { case LOCAL_GL_FRAMEBUFFER: break; case LOCAL_GL_DRAW_FRAMEBUFFER: case LOCAL_GL_READ_FRAMEBUFFER: isValid = IsWebGL2(); break; default: isValid = false; break; } if (MOZ_LIKELY(isValid)) { return true; } ErrorInvalidEnum("%s: Invalid target: %s (0x%04x).", info, EnumName(target), target); return false; }
bool nsCounterManager::AddResetOrIncrement(nsIFrame *aFrame, int32_t aIndex, const nsStyleCounterData *aCounterData, nsCounterNode::Type aType) { nsCounterChangeNode *node = new nsCounterChangeNode(aFrame, aType, aCounterData->mValue, aIndex); nsCounterList *counterList = CounterListFor(aCounterData->mCounter); if (!counterList) { NS_NOTREACHED("CounterListFor failed (should only happen on OOM)"); return false; } counterList->Insert(node); if (!counterList->IsLast(node)) { // Tell the caller it's responsible for recalculating the entire // list. counterList->SetDirty(); return true; } // Don't call Calc() if the list is already dirty -- it'll be recalculated // anyway, and trying to calculate with a dirty list doesn't work. if (MOZ_LIKELY(!counterList->IsDirty())) { node->Calc(counterList); } return false; }
void ComputeHintIfNeeded(nsIContent* aContent, nsIFrame* aTextFrame, nsStyleContext& aNewContext, nsStyleChangeList& aChangeList) { MOZ_ASSERT(aTextFrame); MOZ_ASSERT(aNewContext.GetPseudo() == nsCSSAnonBoxes::mozText); if (MOZ_LIKELY(!mShouldPostHints)) { return; } nsStyleContext* oldContext = aTextFrame->StyleContext(); MOZ_ASSERT(oldContext->GetPseudo() == nsCSSAnonBoxes::mozText); // We rely on the fact that all the text children for the same element share // style to avoid recomputing style differences for all of them. // // TODO(emilio): The above may not be true for ::first-{line,letter}, but // we'll cross that bridge when we support those in stylo. if (mShouldComputeHints) { mShouldComputeHints = false; uint32_t equalStructs, samePointerStructs; mComputedHint = oldContext->CalcStyleDifference(&aNewContext, &equalStructs, &samePointerStructs); } if (mComputedHint) { aChangeList.AppendChange(aTextFrame, aContent, mComputedHint); } }
/** * Scan an Ident token. This also handles Function and URL tokens, * both of which begin indistinguishably from an identifier. It can * produce a Symbol token when an apparent identifier actually led * into an invalid escape sequence. */ bool nsCSSScanner::ScanIdent(nsCSSToken& aToken) { if (MOZ_UNLIKELY(!GatherText(IS_IDCHAR, aToken.mIdent))) { MOZ_ASSERT(Peek() == '\\', "unexpected IsIdentStart character that did not begin an ident"); aToken.mSymbol = Peek(); Advance(); return true; } if (MOZ_LIKELY(Peek() != '(')) { aToken.mType = eCSSToken_Ident; return true; } Advance(); aToken.mType = eCSSToken_Function; if (aToken.mIdent.LowerCaseEqualsLiteral("url")) { NextURL(aToken); } else if (aToken.mIdent.LowerCaseEqualsLiteral("var")) { mSeenVariableReference = true; } return true; }
void DOMStorageDBThread::ThreadFunc() { nsresult rv = InitDatabase(); MonitorAutoLock lockMonitor(mMonitor); if (NS_FAILED(rv)) { mStatus = rv; mStopIOThread = true; return; } while (MOZ_LIKELY(!mStopIOThread || mPreloads.Length() || mPendingTasks.HasTasks())) { if (MOZ_UNLIKELY(TimeUntilFlush() == 0)) { // Flush time is up or flush has been forced, do it now. UnscheduleFlush(); if (mPendingTasks.Prepare()) { { MonitorAutoUnlock unlockMonitor(mMonitor); rv = mPendingTasks.Execute(this); } if (!mPendingTasks.Finalize(rv)) { mStatus = rv; NS_WARNING("localStorage DB access broken"); } } NotifyFlushCompletion(); } else if (MOZ_LIKELY(mPreloads.Length())) { nsAutoPtr<DBOperation> op(mPreloads[0]); mPreloads.RemoveElementAt(0); { MonitorAutoUnlock unlockMonitor(mMonitor); op->PerformAndFinalize(this); } if (op->Type() == DBOperation::opPreloadUrgent) { SetDefaultPriority(); // urgent preload unscheduled } } else if (MOZ_UNLIKELY(!mStopIOThread)) { lockMonitor.Wait(TimeUntilFlush()); } } // thread loop mStatus = ShutdownDatabase(); }
int posix_memalign_impl(void **memptr, size_t alignment, size_t size) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_posix_memalign)) return je_posix_memalign(memptr, alignment, size); return replace_posix_memalign(memptr, alignment, size); }
const CharT* match(uint64_t ref) { if (MOZ_LIKELY(ref < internedStrings.length())) { auto& string = internedStrings[ref]; MOZ_ASSERT(string); return string.get(); } return nullptr; }
size_t malloc_usable_size_impl(usable_ptr_t ptr) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_malloc_usable_size)) return je_malloc_usable_size(ptr); return replace_malloc_usable_size(ptr); }
void* valloc_impl(size_t size) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_valloc)) return je_valloc(size); return replace_valloc(size); }
void* memalign_impl(size_t alignment, size_t size) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_memalign)) return je_memalign(alignment, size); return replace_memalign(alignment, size); }
void* realloc_impl(void *ptr, size_t size) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_realloc)) return je_realloc(ptr, size); return replace_realloc(ptr, size); }
MFBT_API struct ReplaceMallocBridge* get_bridge(void) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_get_bridge)) return NULL; return replace_get_bridge(); }
size_t malloc_good_size_impl(size_t size) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_malloc_good_size)) return je_malloc_good_size(size); return replace_malloc_good_size(size); }
void jemalloc_stats_impl(jemalloc_stats_t *stats) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_jemalloc_stats)) je_jemalloc_stats(stats); else replace_jemalloc_stats(stats); }
void free_impl(void *ptr) { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_free)) je_free(ptr); else replace_free(ptr); }
void jemalloc_free_dirty_pages_impl() { if (MOZ_UNLIKELY(!replace_malloc_initialized)) init(); if (MOZ_LIKELY(!replace_jemalloc_free_dirty_pages)) je_jemalloc_free_dirty_pages(); else replace_jemalloc_free_dirty_pages(); }
nsHtml5OtherDocUpdate(nsIDocument* aCurrentDoc, nsIDocument* aExecutorDoc) { NS_PRECONDITION(aCurrentDoc, "Node has no doc?"); NS_PRECONDITION(aExecutorDoc, "Executor has no doc?"); if (MOZ_LIKELY(aCurrentDoc == aExecutorDoc)) { mDocument = nullptr; } else { mDocument = aCurrentDoc; aCurrentDoc->BeginUpdate(UPDATE_CONTENT_MODEL); } }
void HRTFDatabaseLoader::ProxyRelease() { nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); if (MOZ_LIKELY(mainThread)) { RefPtr<ProxyReleaseEvent> event = new ProxyReleaseEvent(this); DebugOnly<nsresult> rv = mainThread->Dispatch(event, NS_DISPATCH_NORMAL); MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch release event"); } else { // Should be in XPCOM shutdown. MOZ_ASSERT(NS_IsMainThread(), "Main thread is not available for dispatch."); MainThreadRelease(); } }
SourceBufferIterator::State SourceBufferIterator::AdvanceOrScheduleResume(size_t aRequestedBytes, IResumable* aConsumer) { MOZ_ASSERT(mOwner); if (MOZ_UNLIKELY(!HasMore())) { MOZ_ASSERT_UNREACHABLE("Should not advance a completed iterator"); return COMPLETE; } // The range of data [mOffset, mOffset + mNextReadLength) has just been read // by the caller (or at least they don't have any interest in it), so consume // that data. MOZ_ASSERT(mData.mIterating.mNextReadLength <= mData.mIterating.mAvailableLength); mData.mIterating.mOffset += mData.mIterating.mNextReadLength; mData.mIterating.mAvailableLength -= mData.mIterating.mNextReadLength; mData.mIterating.mNextReadLength = 0; if (MOZ_LIKELY(mState == READY)) { // If the caller wants zero bytes of data, that's easy enough; we just // configured ourselves for a zero-byte read above! In theory we could do // this even in the START state, but it's not important for performance and // breaking the ability of callers to assert that the pointer returned by // Data() is non-null doesn't seem worth it. if (aRequestedBytes == 0) { MOZ_ASSERT(mData.mIterating.mNextReadLength == 0); return READY; } // Try to satisfy the request out of our local buffer. This is potentially // much faster than requesting data from our owning SourceBuffer because we // don't have to take the lock. Note that if we have anything at all in our // local buffer, we use it to satisfy the request; @aRequestedBytes is just // the *maximum* number of bytes we can return. if (mData.mIterating.mAvailableLength > 0) { return AdvanceFromLocalBuffer(aRequestedBytes); } } // Our local buffer is empty, so we'll have to request data from our owning // SourceBuffer. return mOwner->AdvanceIteratorOrScheduleResume(*this, aRequestedBytes, aConsumer); }
void PDUInitOp::WarnAboutTrailingData() const { size_t size = mPDU->GetSize(); if (MOZ_LIKELY(!size)) { return; } uint8_t service, opcode; uint16_t payloadSize; mPDU->GetHeader(service, opcode, payloadSize); CHROMIUM_LOG( "Unpacked PDU of type (%x,%x) still contains %zu Bytes of data.", service, opcode, size); }
void nsLineBox::NoteFramesMovedFrom(nsLineBox* aFromLine) { uint32_t fromCount = aFromLine->GetChildCount(); uint32_t toCount = GetChildCount(); MOZ_ASSERT(toCount <= fromCount, "moved more frames than aFromLine has"); uint32_t fromNewCount = fromCount - toCount; if (MOZ_LIKELY(!aFromLine->mFlags.mHasHashedFrames)) { aFromLine->mChildCount = fromNewCount; MOZ_ASSERT(toCount < kMinChildCountForHashtable); } else if (fromNewCount < kMinChildCountForHashtable) { // aFromLine has a hash table but will not have it after moving the frames // so this line can steal the hash table if it needs it. if (toCount >= kMinChildCountForHashtable) { StealHashTableFrom(aFromLine, fromNewCount); } else { delete aFromLine->mFrames; aFromLine->mFlags.mHasHashedFrames = 0; aFromLine->mChildCount = fromNewCount; } } else { // aFromLine still needs a hash table. if (toCount < kMinChildCountForHashtable) { // remove the moved frames from it nsIFrame* f = mFirstChild; for (uint32_t i = 0; i < toCount; f = f->GetNextSibling(), ++i) { aFromLine->mFrames->RemoveEntry(f); } } else if (toCount <= fromNewCount) { // This line needs a hash table, allocate a hash table for it since that // means fewer hash ops. nsIFrame* f = mFirstChild; for (uint32_t i = 0; i < toCount; f = f->GetNextSibling(), ++i) { aFromLine->mFrames->RemoveEntry(f); // toCount RemoveEntry } SwitchToHashtable(); // toCount PutEntry } else { // This line needs a hash table, but it's fewer hash ops to steal // aFromLine's hash table and allocate a new hash table for that line. StealHashTableFrom(aFromLine, fromNewCount); // fromNewCount RemoveEntry aFromLine->SwitchToHashtable(); // fromNewCount PutEntry } } }
// // CreatePrimitiveForData // // Given some data and the flavor it corresponds to, creates the appropriate // nsISupports* wrapper for passing across IDL boundaries. Right now, everything // creates a two-byte |nsISupportsString|, except for "text/plain" and native // platform HTML (CF_HTML on win32) // void nsPrimitiveHelpers :: CreatePrimitiveForData ( const char* aFlavor, const void* aDataBuff, uint32_t aDataLen, nsISupports** aPrimitive ) { if ( !aPrimitive ) return; if ( strcmp(aFlavor,kTextMime) == 0 || strcmp(aFlavor,kNativeHTMLMime) == 0 || strcmp(aFlavor,kRTFMime) == 0 || strcmp(aFlavor,kCustomTypesMime) == 0) { nsCOMPtr<nsISupportsCString> primitive = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID); if ( primitive ) { const char * start = reinterpret_cast<const char*>(aDataBuff); primitive->SetData(Substring(start, start + aDataLen)); NS_ADDREF(*aPrimitive = primitive); } } else { nsCOMPtr<nsISupportsString> primitive = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); if (primitive ) { if (aDataLen % 2) { auto buffer = mozilla::MakeUnique<char[]>(aDataLen + 1); if (!MOZ_LIKELY(buffer)) return; memcpy(buffer.get(), aDataBuff, aDataLen); buffer[aDataLen] = 0; const char16_t* start = reinterpret_cast<const char16_t*>(buffer.get()); // recall that length takes length as characters, not bytes primitive->SetData(Substring(start, start + (aDataLen + 1) / 2)); } else { const char16_t* start = reinterpret_cast<const char16_t*>(aDataBuff); // recall that length takes length as characters, not bytes primitive->SetData(Substring(start, start + (aDataLen / 2))); } NS_ADDREF(*aPrimitive = primitive); } } } // CreatePrimitiveForData
/** * This method consumes a start tag and all of its attributes. * * @param aChar The last character read from the scanner. * @param aToken The OUT parameter that holds our resulting token. (allocated * by the function using mTokenAllocator * @param aScanner Our source of data * @param aFlushTokens is an OUT parameter use to tell consumers to flush * the current tokens after processing the current one. * @return Error result. */ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar, CToken*& aToken, nsScanner& aScanner, bool& aFlushTokens) { // Remember this for later in case you have to unwind... int32_t theDequeSize = mTokenDeque.GetSize(); nsresult result = NS_OK; nsTokenAllocator* theAllocator = this->GetTokenAllocator(); aToken = theAllocator->CreateTokenOfType(eToken_start, eHTMLTag_unknown); NS_ENSURE_TRUE(aToken, NS_ERROR_OUT_OF_MEMORY); // Tell the new token to finish consuming text... result = aToken->Consume(aChar, aScanner, mFlags); if (NS_SUCCEEDED(result)) { AddToken(aToken, result, &mTokenDeque, theAllocator); eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID(); // Good. Now, let's see if the next char is ">". // If so, we have a complete tag, otherwise, we have attributes. result = aScanner.Peek(aChar); if (NS_FAILED(result)) { aToken->SetInError(true); // Don't return early here so we can create a text and end token for // the special <iframe>, <script> and similar tags down below. result = NS_OK; } else { if (kGreaterThan != aChar) { // Look for a '>' result = ConsumeAttributes(aChar, aToken, aScanner); } else { aScanner.GetChar(aChar); } } /* Now that that's over with, we have one more problem to solve. In the case that we just read a <SCRIPT> or <STYLE> tags, we should go and consume all the content itself. But XML doesn't treat these tags differently, so we shouldn't if the document is XML. */ if (NS_SUCCEEDED(result) && !(mFlags & NS_IPARSER_FLAG_XML)) { bool isCDATA = gHTMLElements[theTag].CanContainType(kCDATA); bool isPCDATA = eHTMLTag_textarea == theTag || eHTMLTag_title == theTag; // XXX This is an evil hack, we should be able to handle these properly // in the DTD. if ((eHTMLTag_iframe == theTag && (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) || (eHTMLTag_noframes == theTag && (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) || (eHTMLTag_noscript == theTag && (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED)) || (eHTMLTag_noembed == theTag)) { isCDATA = true; } // Plaintext contains CDATA, but it's special, so we handle it // differently than the other CDATA elements if (eHTMLTag_plaintext == theTag) { isCDATA = false; // Note: We check in ConsumeToken() for this flag, and if we see it // we only construct text tokens (which is what we want). mFlags |= NS_IPARSER_FLAG_PLAIN_TEXT; } if (isCDATA || isPCDATA) { bool done = false; nsDependentString endTagName(nsHTMLTags::GetStringValue(theTag)); CToken* text = theAllocator->CreateTokenOfType(eToken_text, eHTMLTag_text); NS_ENSURE_TRUE(text, NS_ERROR_OUT_OF_MEMORY); CTextToken* textToken = static_cast<CTextToken*>(text); if (isCDATA) { result = textToken->ConsumeCharacterData(theTag != eHTMLTag_script, aScanner, endTagName, mFlags, done); // Only flush tokens for <script>, to give ourselves more of a // chance of allowing inlines to contain blocks. aFlushTokens = done && theTag == eHTMLTag_script; } else if (isPCDATA) { // Title is consumed conservatively in order to not regress // bug 42945 result = textToken->ConsumeParsedCharacterData( theTag == eHTMLTag_textarea, theTag == eHTMLTag_title, aScanner, endTagName, mFlags, done); // Note: we *don't* set aFlushTokens here. } // We want to do this unless result is kEOF, in which case we will // simply unwind our stack and wait for more data anyway. if (kEOF != result) { AddToken(text, NS_OK, &mTokenDeque, theAllocator); CToken* endToken = nullptr; if (NS_SUCCEEDED(result) && done) { PRUnichar theChar; // Get the < result = aScanner.GetChar(theChar); NS_ASSERTION(NS_SUCCEEDED(result) && theChar == kLessThan, "CTextToken::Consume*Data is broken!"); #ifdef DEBUG // Ensure we have a / PRUnichar tempChar; // Don't change non-debug vars in debug-only code result = aScanner.Peek(tempChar); NS_ASSERTION(NS_SUCCEEDED(result) && tempChar == kForwardSlash, "CTextToken::Consume*Data is broken!"); #endif result = ConsumeEndTag(PRUnichar('/'), endToken, aScanner); if (!(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE) && NS_SUCCEEDED(result)) { // If ConsumeCharacterData returned a success result (and // we're not in view source), then we want to make sure that // we're going to execute this script (since the result means // that we've found an end tag that satisfies all of the right // conditions). endToken->SetInError(false); } } else if (result == kFakeEndTag && !(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE)) { result = NS_OK; endToken = theAllocator->CreateTokenOfType(eToken_end, theTag, endTagName); AddToken(endToken, result, &mTokenDeque, theAllocator); if (MOZ_LIKELY(endToken != nullptr)) { endToken->SetInError(true); } else { result = NS_ERROR_OUT_OF_MEMORY; } } else if (result == kFakeEndTag) { // If we are here, we are both faking having seen the end tag // and are in view-source. result = NS_OK; } } else { IF_FREE(text, mTokenAllocator); } } } // This code is confusing, so pay attention. // If you're here, it's because we were in the midst of consuming a start // tag but ran out of data (not in the stream, but in this *part* of the // stream. For simplicity, we have to unwind our input. Therefore, we pop // and discard any new tokens we've queued this round. Later we can get // smarter about this. if (NS_FAILED(result)) { while (mTokenDeque.GetSize()>theDequeSize) { CToken* theToken = (CToken*)mTokenDeque.Pop(); IF_FREE(theToken, mTokenAllocator); } } } else { IF_FREE(aToken, mTokenAllocator); } return result; }
/** * This method is called just after we've consumed a start or end * tag, and we now have to consume its attributes. * * @param aChar is the last char read * @param aToken is the start or end tag that "owns" these attributes. * @param aScanner represents our input source * @return Error result. */ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar, CToken* aToken, nsScanner& aScanner) { bool done = false; nsresult result = NS_OK; int16_t theAttrCount = 0; nsTokenAllocator* theAllocator = this->GetTokenAllocator(); while (!done && result == NS_OK) { CAttributeToken* theToken = static_cast<CAttributeToken*> (theAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown)); if (MOZ_LIKELY(theToken != nullptr)) { // Tell the new token to finish consuming text... result = theToken->Consume(aChar, aScanner, mFlags); if (NS_SUCCEEDED(result)) { ++theAttrCount; AddToken((CToken*&)theToken, result, &mTokenDeque, theAllocator); } else { IF_FREE(theToken, mTokenAllocator); // Bad attribute returns shouldn't propagate out. if (NS_ERROR_HTMLPARSER_BADATTRIBUTE == result) { result = NS_OK; } } } else { result = NS_ERROR_OUT_OF_MEMORY; } #ifdef DEBUG if (NS_SUCCEEDED(result)) { int32_t newline = 0; aScanner.SkipWhitespace(newline); NS_ASSERTION(newline == 0, "CAttribute::Consume() failed to collect all the newlines!"); } #endif if (NS_SUCCEEDED(result)) { result = aScanner.Peek(aChar); if (NS_SUCCEEDED(result)) { if (aChar == kGreaterThan) { // You just ate the '>' aScanner.GetChar(aChar); // Skip the '>' done = true; } else if (aChar == kLessThan) { aToken->SetInError(true); done = true; } } } } if (NS_FAILED(result)) { aToken->SetInError(true); if (!aScanner.IsIncremental()) { result = NS_OK; } } aToken->SetAttributeCount(theAttrCount); return result; }