Пример #1
0
/**
 *  This method gets called when a tag needs to write it's attributes
 *
 *  @update  gess 3/25/98
 *  @param
 *  @return  result status
 */
nsresult CViewSourceHTML::WriteAttributes(const nsAString& tagName, 
                                          nsTokenAllocator* allocator, 
                                          PRInt32 attrCount, PRBool aOwnerInError) {
  nsresult result=NS_OK;

  if(attrCount){ //go collect the attributes...
    int attr = 0;
    for(attr = 0; attr < attrCount; ++attr){
      CToken* theToken = mTokenizer->PeekToken();
      if(theToken)  {
        eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
        if(eToken_attribute == theType){
          mTokenizer->PopToken(); //pop it for real...
          mTokenNode.AddAttribute(theToken);  //and add it to the node.

          CAttributeToken* theAttrToken = (CAttributeToken*)theToken;
          const nsSubstring& theKey = theAttrToken->GetKey();

          // The attribute is only in error if its owner is NOT in error.
          const PRBool attributeInError =
            !aOwnerInError && theAttrToken->IsInError();

          result = WriteTag(kAttributeName,theKey,0,attributeInError);
          const nsSubstring& theValue = theAttrToken->GetValue();

          if(!theValue.IsEmpty() || theAttrToken->mHasEqualWithoutValue){
            if (IsUrlAttribute(tagName, theKey, theValue)) {
              WriteHrefAttribute(allocator, theValue);
            } else {
              WriteTag(kAttributeValue,theValue,0,attributeInError);
            }
          }
        }
      }
      else return kEOF;
    }
  }

  return result;
}
/**
 * This method scans the sequence of tokens to determine whether or not the
 * tag structure of the document is well formed. In well formed cases, we can
 * skip doing residual style handling and allow inlines to contain block-level
 * elements.
 *
 * @param aFinalChunk Is unused.
 * @return Success (currently, this function cannot fail).
 */
nsresult nsHTMLTokenizer::ScanDocStructure(bool aFinalChunk)
{
  nsresult result = NS_OK;
  if (!mTokenDeque.GetSize()) {
    return result;
  }

  CHTMLToken* theToken = (CHTMLToken*)mTokenDeque.ObjectAt(mTokenScanPos);

  // Start by finding the first start tag that hasn't been reviewed.
  while (mTokenScanPos > 0) {
    if (theToken) {
      eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());  
      if (theType == eToken_start &&
          theToken->GetContainerInfo() == eFormUnknown) {
        break;
      }
    }
    theToken = (CHTMLToken*)mTokenDeque.ObjectAt(--mTokenScanPos);
  }

  // Now that we know where to start, let's walk through the
  // tokens to see which are well-formed. Stop when you run out
  // of fresh tokens.

  nsDeque       theStack(0);
  nsDeque       tempStack(0);
  int32_t       theStackDepth = 0;
  // Don't bother if we get ridiculously deep.
  static  const int32_t theMaxStackDepth = 200;

  while (theToken && theStackDepth < theMaxStackDepth) {
    eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType());
    eHTMLTags       theTag  = (eHTMLTags)theToken->GetTypeID();

    if (nsHTMLElement::IsContainer(theTag)) { // Bug 54117
      bool theTagIsBlock  = gHTMLElements[theTag].IsMemberOf(kBlockEntity);
      bool theTagIsInline = theTagIsBlock
                              ? false
                              : gHTMLElements[theTag].IsMemberOf(kInlineEntity);

      if (theTagIsBlock || theTagIsInline || eHTMLTag_table == theTag) {
        switch(theType) {
          case eToken_start:
            {
              if (gHTMLElements[theTag].ShouldVerifyHierarchy()) {
                int32_t earlyPos = FindLastIndexOfTag(theTag, theStack);
                if (earlyPos != kNotFound) {
                  // Uh-oh, we've found a tag that is not allowed to nest at
                  // all. Mark the previous one and all of its children as 
                  // malformed to increase our chances of doing RS handling
                  // on all of them. We want to do this for cases such as:
                  // <a><div><a></a></div></a>.
                  // Note that we have to iterate through all of the chilren
                  // of the original malformed tag to protect against:
                  // <a><font><div><a></a></div></font></a>, so that the <font>
                  // is allowed to contain the <div>.
                  // XXX What about <a><span><a>, where the second <a> closes
                  // the <span>?
                  nsDequeIterator it(theStack, earlyPos), end(theStack.End());
                  while (it < end) {
                    CHTMLToken *theMalformedToken = 
                        static_cast<CHTMLToken*>(it++);
                  
                    theMalformedToken->SetContainerInfo(eMalformed);
                  }
                }
              }

              theStack.Push(theToken);
              ++theStackDepth;
            }
            break;
          case eToken_end: 
            {
              CHTMLToken *theLastToken =
                static_cast<CHTMLToken*>(theStack.Peek());
              if (theLastToken) {
                if (theTag == theLastToken->GetTypeID()) {
                  theStack.Pop(); // Yank it for real 
                  theStackDepth--;
                  theLastToken->SetContainerInfo(eWellFormed);
                } else {
                  // This token wasn't what we expected it to be! We need to
                  // go searching for its real start tag on our stack. Each
                  // tag in between the end tag and start tag must be malformed

                  if (FindLastIndexOfTag(theTag, theStack) != kNotFound) {
                    // Find theTarget in the stack, marking each (malformed!)
                    // tag in our way.
                    theStack.Pop(); // Pop off theLastToken for real.
                    do {
                      theLastToken->SetContainerInfo(eMalformed);
                      tempStack.Push(theLastToken);
                      theLastToken = static_cast<CHTMLToken*>(theStack.Pop());
                    } while (theLastToken && theTag != theLastToken->GetTypeID());
                    // XXX The above test can confuse two different userdefined 
                    // tags.

                    NS_ASSERTION(theLastToken,
                                 "FindLastIndexOfTag lied to us!"
                                 " We couldn't find theTag on theStack");
                    theLastToken->SetContainerInfo(eMalformed);

                    // Great, now push all of the other tokens back onto the
                    // stack to preserve the general structure of the document.
                    // Note that we don't push the target token back onto the
                    // the stack (since it was just closed).
                    while (tempStack.GetSize() != 0) {
                      theStack.Push(tempStack.Pop());
                    }
                  }
                }
              }
            }
            break;
          default:
            break; 
        }
      }
    }

    theToken = (CHTMLToken*)mTokenDeque.ObjectAt(++mTokenScanPos);
  }

  return result;
}
Пример #3
0
nsNodeAllocator::nsNodeAllocator():mSharedNodes(0){
#ifdef DEBUG_TRACK_NODES
  mCount=0;
#endif
#else 
  static const size_t  kNodeBuckets[]       = { sizeof(nsCParserNode), sizeof(nsCParserStartNode) };
  static const PRInt32 kNumNodeBuckets      = sizeof(kNodeBuckets) / sizeof(size_t);
  static const PRInt32 kInitialNodePoolSize = NS_SIZE_IN_HEAP(sizeof(nsCParserNode)) * 35; // optimal size based on space-trace data
nsNodeAllocator::nsNodeAllocator() {
  mNodePool.Init("NodePool", kNodeBuckets, kNumNodeBuckets, kInitialNodePoolSize);
#endif
  MOZ_COUNT_CTOR(nsNodeAllocator);
}
  
nsNodeAllocator::~nsNodeAllocator() {
  MOZ_COUNT_DTOR(nsNodeAllocator);

#ifdef HEAP_ALLOCATED_NODES
  nsCParserNode* theNode = 0;

  while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
#ifdef DEBUG_TRACK_NODES
    RemoveNode(theNode);
#endif
    ::operator delete(theNode); 
    theNode=nsnull;
  }
#ifdef DEBUG_TRACK_NODES
  if(mCount) {
    printf("**************************\n");
    printf("%i out of %i nodes leaked!\n",gAllNodeCount,mCount);
    printf("**************************\n");
  }
#endif
#endif
}
  
nsCParserNode* nsNodeAllocator::CreateNode(CToken* aToken,  
                                           nsTokenAllocator* aTokenAllocator) 
{
  nsCParserNode* result = 0;
#ifdef HEAP_ALLOCATED_NODES
#if 0
  if(gAllNodeCount!=mSharedNodes.GetSize()) {
    int x=10; //this is very BAD!
  }
#endif
  result = static_cast<nsCParserNode*>(mSharedNodes.Pop());
  if (result) {
    result->Init(aToken, aTokenAllocator,this);
  }
  else{
    result = nsCParserNode::Create(aToken, aTokenAllocator,this);
#ifdef DEBUG_TRACK_NODES
    ++mCount;
    AddNode(static_cast<nsCParserNode*>(result));
#endif
    IF_HOLD(result);
  }
#else
  eHTMLTokenTypes type = aToken ? eHTMLTokenTypes(aToken->GetTokenType()) : eToken_unknown;
  switch (type) {
    case eToken_start:
      result = nsCParserStartNode::Create(aToken, aTokenAllocator,this); 
      break;
    default :
      result = nsCParserNode::Create(aToken, aTokenAllocator,this); 
      break;
  }
  IF_HOLD(result);
#endif
  return result;
}