OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 ASSERT(m_haveBackgroundParser); | 152 ASSERT(m_haveBackgroundParser); |
153 pumpPendingChunks(); | 153 pumpPendingChunks(); |
154 } | 154 } |
155 | 155 |
156 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() | 156 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() |
157 { | 157 { |
158 if (m_isFragment) | 158 if (m_isFragment) |
159 return; | 159 return; |
160 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); | 160 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); |
161 RefPtr<Element> scriptToProcess = m_treeBuilder->takeScriptToProcess(scriptS tartPosition); | 161 RefPtr<Element> scriptToProcess = m_treeBuilder->takeScriptToProcess(scriptS tartPosition); |
162 m_scriptRunner.runScript(toHTMLScriptElement(scriptToProcess.get()), scriptS tartPosition); | 162 |
163 // Sending the script to dart may find additional 'import' declarations | |
164 // which need to load before the script can execute. HTMLScriptRunner | |
165 // always calls scriptExecutionCompleted regardless of success/failure. | |
166 m_scriptRunner = HTMLScriptRunner::createForScript( | |
167 toHTMLScriptElement(scriptToProcess.get()), scriptStartPosition, this); | |
168 m_scriptRunner->start(); | |
163 } | 169 } |
164 | 170 |
165 void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa rsedChunk> chunk) | 171 void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa rsedChunk> chunk) |
166 { | 172 { |
167 TRACE_EVENT0("blink", "HTMLDocumentParser::didReceiveParsedChunkFromBackgrou ndParser"); | 173 TRACE_EVENT0("blink", "HTMLDocumentParser::didReceiveParsedChunkFromBackgrou ndParser"); |
168 // Sky should not need nested parsers. | 174 // Sky should not need nested parsers. |
169 ASSERT(document()->activeParserCount() == 0); | 175 ASSERT(document()->activeParserCount() == 0); |
170 | 176 |
171 if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || document()->activ eParserCount() > 0 || !document()->haveImportsLoaded()) { | 177 if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || |
178 document()->activeParserCount() > 0) { | |
172 m_pendingChunks.append(chunk); | 179 m_pendingChunks.append(chunk); |
173 return; | 180 return; |
174 } | 181 } |
175 | 182 |
176 // processParsedChunkFromBackgroundParser can cause this parser to be detach ed from the Document, | 183 // processParsedChunkFromBackgroundParser can cause this parser to be detach ed from the Document, |
177 // but we need to ensure it isn't deleted yet. | 184 // but we need to ensure it isn't deleted yet. |
178 RefPtr<HTMLDocumentParser> protect(this); | 185 RefPtr<HTMLDocumentParser> protect(this); |
179 | 186 |
180 ASSERT(m_pendingChunks.isEmpty()); | 187 ASSERT(m_pendingChunks.isEmpty()); |
181 m_pendingChunks.append(chunk); | 188 m_pendingChunks.append(chunk); |
(...skipping 11 matching lines...) Expand all Loading... | |
193 ASSERT(!isStopped()); | 200 ASSERT(!isStopped()); |
194 | 201 |
195 // ASSERT that this object is both attached to the Document and protected. | 202 // ASSERT that this object is both attached to the Document and protected. |
196 ASSERT(refCount() >= 2); | 203 ASSERT(refCount() >= 2); |
197 | 204 |
198 ActiveParserSession session(contextForParsingSession()); | 205 ActiveParserSession session(contextForParsingSession()); |
199 | 206 |
200 OwnPtr<ParsedChunk> chunk(popChunk); | 207 OwnPtr<ParsedChunk> chunk(popChunk); |
201 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); | 208 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); |
202 | 209 |
203 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { | 210 Vector<CompactHTMLToken>::const_iterator it; |
204 ASSERT(!isWaitingForScripts()); | 211 for (it = tokens->begin(); it != tokens->end(); ++it) { |
212 // A chunk can issue import loads causing us to be isWaitingForScripts | |
213 // but we don't stop processing in that case. | |
214 ASSERT(!m_treeBuilder->hasParserBlockingScript()); | |
215 ASSERT(!m_scriptRunner); | |
205 | 216 |
206 m_textPosition = it->textPosition(); | 217 m_textPosition = it->textPosition(); |
207 | 218 |
208 constructTreeFromCompactHTMLToken(*it); | 219 constructTreeFromCompactHTMLToken(*it); |
209 | 220 |
210 if (isStopped()) | 221 if (isStopped()) |
211 break; | 222 break; |
212 | 223 |
213 if (isWaitingForScripts()) { | 224 if (m_treeBuilder->hasParserBlockingScript()) { |
214 ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be t he last token of this bunch. | 225 ASSERT(++it == tokens->end()); // The </script> is assumed to be the |
abarth-chromium
2015/02/19 02:51:40
s/++it/it + 1/ ?
It seems very dangerous to mutat
| |
226 // last token of this bunch. | |
215 runScriptsForPausedTreeBuilder(); | 227 runScriptsForPausedTreeBuilder(); |
216 break; | 228 break; |
217 } | 229 } |
218 | 230 |
219 if (it->type() == HTMLToken::EndOfFile) { | 231 if (it->type() == HTMLToken::EndOfFile) { |
220 ASSERT(it + 1 == tokens->end()); // The EOF is assumed to be the las t token of this bunch. | 232 ASSERT(++it == tokens->end()); // The EOF is assumed to be the last |
abarth-chromium
2015/02/19 02:51:40
Ditto
| |
233 // token of this bunch. | |
221 ASSERT(m_pendingChunks.isEmpty()); // There should never be any chun ks after the EOF. | 234 ASSERT(m_pendingChunks.isEmpty()); // There should never be any chun ks after the EOF. |
222 prepareToStopParsing(); | 235 prepareToStopParsing(); |
223 break; | 236 break; |
224 } | 237 } |
225 } | 238 } |
226 | 239 |
240 // Either we aborted due to stopping or we processed all tokens. | |
241 ASSERT(isStopped() || it == tokens->end()); | |
abarth-chromium
2015/02/19 02:51:40
I see... Maybe move the ++it outside of the ASSER
| |
242 | |
227 // Make sure any pending text nodes are emitted before returning. | 243 // Make sure any pending text nodes are emitted before returning. |
228 if (!isStopped()) | 244 if (!isStopped()) |
229 m_treeBuilder->flush(); | 245 m_treeBuilder->flush(); |
230 } | 246 } |
231 | 247 |
232 void HTMLDocumentParser::pumpPendingChunks() | 248 void HTMLDocumentParser::pumpPendingChunks() |
233 { | 249 { |
234 // FIXME: Share this constant with the parser scheduler. | 250 // FIXME: Share this constant with the parser scheduler. |
235 const double parserTimeLimit = 0.500; | 251 const double parserTimeLimit = 0.500; |
236 | 252 |
237 // ASSERT that this object is both attached to the Document and protected. | 253 // ASSERT that this object is both attached to the Document and protected. |
238 ASSERT(refCount() >= 2); | 254 ASSERT(refCount() >= 2); |
239 ASSERT(!isWaitingForScripts()); | 255 ASSERT(!isWaitingForScripts()); |
240 ASSERT(!isStopped()); | 256 ASSERT(!isStopped()); |
241 ASSERT(document()->haveImportsLoaded()); | |
242 | 257 |
243 double startTime = currentTime(); | 258 double startTime = currentTime(); |
244 | 259 |
245 while (!m_pendingChunks.isEmpty()) { | 260 while (!m_pendingChunks.isEmpty()) { |
246 processParsedChunkFromBackgroundParser(m_pendingChunks.takeFirst()); | 261 processParsedChunkFromBackgroundParser(m_pendingChunks.takeFirst()); |
247 | 262 |
248 // Always check isStopped first as m_document may be null. | 263 // Always check isStopped first as m_document may be null. |
249 if (isStopped() || isWaitingForScripts() || !document()->haveImportsLoad ed()) | 264 if (isStopped() || isWaitingForScripts()) |
250 break; | 265 break; |
251 | 266 |
252 if (currentTime() - startTime > parserTimeLimit && !m_pendingChunks.isEm pty()) { | 267 if (currentTime() - startTime > parserTimeLimit && !m_pendingChunks.isEm pty()) { |
253 m_parserScheduler->scheduleForResume(); | 268 m_parserScheduler->scheduleForResume(); |
254 break; | 269 break; |
255 } | 270 } |
256 } | 271 } |
257 } | 272 } |
258 | 273 |
259 Document* HTMLDocumentParser::contextForParsingSession() | 274 Document* HTMLDocumentParser::contextForParsingSession() |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
346 | 361 |
347 if (!m_endWasDelayed || shouldDelayEnd()) | 362 if (!m_endWasDelayed || shouldDelayEnd()) |
348 return; | 363 return; |
349 | 364 |
350 m_endWasDelayed = false; | 365 m_endWasDelayed = false; |
351 prepareToStopParsing(); | 366 prepareToStopParsing(); |
352 } | 367 } |
353 | 368 |
354 bool HTMLDocumentParser::isExecutingScript() const | 369 bool HTMLDocumentParser::isExecutingScript() const |
355 { | 370 { |
356 return m_scriptRunner.isExecutingScript(); | 371 // TODO(eseidel): Callers may need updates now that scripts can be async. |
372 return m_scriptRunner && m_scriptRunner->isExecutingScript(); | |
abarth-chromium
2015/02/19 02:51:40
four-space indent
| |
357 } | 373 } |
358 | 374 |
359 OrdinalNumber HTMLDocumentParser::lineNumber() const | 375 OrdinalNumber HTMLDocumentParser::lineNumber() const |
360 { | 376 { |
361 ASSERT(m_haveBackgroundParser); | 377 ASSERT(m_haveBackgroundParser); |
362 return m_textPosition.m_line; | 378 return m_textPosition.m_line; |
363 } | 379 } |
364 | 380 |
365 TextPosition HTMLDocumentParser::textPosition() const | 381 TextPosition HTMLDocumentParser::textPosition() const |
366 { | 382 { |
367 ASSERT(m_haveBackgroundParser); | 383 ASSERT(m_haveBackgroundParser); |
368 return m_textPosition; | 384 return m_textPosition; |
369 } | 385 } |
370 | 386 |
371 bool HTMLDocumentParser::isWaitingForScripts() const | 387 bool HTMLDocumentParser::isWaitingForScripts() const |
372 { | 388 { |
373 return m_treeBuilder->hasParserBlockingScript(); | 389 return m_treeBuilder->hasParserBlockingScript() || m_scriptRunner || |
390 !document()->haveImportsLoaded(); | |
374 } | 391 } |
375 | 392 |
376 void HTMLDocumentParser::resumeAfterWaitingForImports() | 393 void HTMLDocumentParser::resumeAfterWaitingForImports() |
377 { | 394 { |
378 RefPtr<HTMLDocumentParser> protect(this); | 395 RefPtr<HTMLDocumentParser> protect(this); |
379 ASSERT(!isExecutingScript()); | |
380 ASSERT(!isWaitingForScripts()); | 396 ASSERT(!isWaitingForScripts()); |
381 if (m_pendingChunks.isEmpty()) | 397 if (m_pendingChunks.isEmpty()) |
382 return; | 398 return; |
383 ASSERT(m_haveBackgroundParser); | 399 ASSERT(m_haveBackgroundParser); |
384 pumpPendingChunks(); | 400 pumpPendingChunks(); |
385 } | 401 } |
386 | 402 |
403 // HTMLScriptRunner has finished executing a script. | |
404 // Just call resumeAfterWaitingForImports since it happens to do what we need. | |
405 void HTMLDocumentParser::scriptExecutionCompleted() { | |
406 ASSERT(m_scriptRunner); | |
407 m_scriptRunner.clear(); | |
408 // To avoid re-entering the parser for synchronous scripts, we use a postTask. | |
409 base::MessageLoop::current()->PostTask( | |
410 FROM_HERE, base::Bind(&HTMLDocumentParser::resumeAfterWaitingForImports, | |
411 m_weakFactory.GetWeakPtr())); | |
387 } | 412 } |
413 } | |
OLD | NEW |