Ejemplo n.º 1
0
nsHtml5Parser::UnblockParser()
{
  MOZ_DIAGNOSTIC_ASSERT(mBlocked > 0);
  if (MOZ_LIKELY(mBlocked > 0)) {
    mBlocked--;
  }
  if (MOZ_LIKELY(mBlocked == 0)) {
    mExecutor->ContinueInterruptedParsingAsync();
  }
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 8
0
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);
    }
  }
Ejemplo n.º 10
0
/**
 * 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;
}
Ejemplo n.º 11
0
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();
}
Ejemplo n.º 12
0
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);
}
Ejemplo n.º 13
0
  const CharT* match(uint64_t ref) {
    if (MOZ_LIKELY(ref < internedStrings.length())) {
      auto& string = internedStrings[ref];
      MOZ_ASSERT(string);
      return string.get();
    }

    return nullptr;
  }
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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);
}
Ejemplo n.º 16
0
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);
}
Ejemplo n.º 17
0
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);
}
Ejemplo n.º 18
0
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();
}
Ejemplo n.º 19
0
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);
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
void
free_impl(void *ptr)
{
  if (MOZ_UNLIKELY(!replace_malloc_initialized))
    init();
  if (MOZ_LIKELY(!replace_free))
    je_free(ptr);
  else
    replace_free(ptr);
}
Ejemplo n.º 22
0
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);        
   }
 }
Ejemplo n.º 24
0
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();
    }
}
Ejemplo n.º 25
0
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);
}
Ejemplo n.º 27
0
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
    }
  }
}
Ejemplo n.º 28
0
//
// 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;
}