1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef ScriptStreamer_h 6 #define ScriptStreamer_h 7 8 #include "core/dom/PendingScript.h" 9 #include "wtf/RefCounted.h" 10 11 #include <v8.h> 12 13 namespace blink { 14 15 class PendingScript; 16 class Resource; 17 class ScriptResource; 18 class ScriptResourceClient; 19 class ScriptState; 20 class Settings; 21 class SourceStream; 22 23 // ScriptStreamer streams incomplete script data to V8 so that it can be parsed 24 // while it's loaded. PendingScript holds a reference to ScriptStreamer. At the 25 // moment, ScriptStreamer is only used for parser blocking scripts; this means 26 // that the Document stays stable and no other scripts are executing while we're 27 // streaming. It is possible, though, that Document and the PendingScript are 28 // destroyed while the streaming is in progress, and ScriptStreamer handles it 29 // gracefully. 30 class ScriptStreamer : public RefCounted<ScriptStreamer> { 31 WTF_MAKE_NONCOPYABLE(ScriptStreamer); 32 public: 33 // Launches a task (on a background thread) which will stream the given 34 // PendingScript into V8 as it loads. It's also possible that V8 cannot 35 // stream the given script; in that case this function returns 36 // false. Internally, this constructs a ScriptStreamer and attaches it to 37 // the PendingScript. Use ScriptStreamer::addClient to get notified when the 38 // streaming finishes. 39 static void startStreaming(PendingScript&, Settings*, ScriptState*, PendingScript::Type); 40 41 bool isFinished() const 42 { 43 return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed); 44 } 45 46 v8::ScriptCompiler::StreamedSource* source() { return &m_source; } 47 ScriptResource* resource() const { return m_resource; } 48 49 // Called when the script is not needed any more (e.g., loading was 50 // cancelled). After calling cancel, PendingScript can drop its reference to 51 // ScriptStreamer, and ScriptStreamer takes care of eventually deleting 52 // itself (after the V8 side has finished too). 53 void cancel(); 54 55 // When the streaming is suppressed, the data is not given to V8, but 56 // ScriptStreamer still watches the resource load and notifies the upper 57 // layers when loading is finished. It is used in situations when we have 58 // started streaming but then we detect we don't want to stream (e.g., when 59 // we have the code cache for the script) and we still want to parse and 60 // execute it when it has finished loading. 61 void suppressStreaming(); 62 bool streamingSuppressed() const { return m_streamingSuppressed; } 63 64 unsigned cachedDataType() const { return m_cachedDataType; } 65 66 void addClient(ScriptResourceClient* client) 67 { 68 ASSERT(!m_client); 69 ASSERT(!isFinished()); 70 m_client = client; 71 } 72 73 void removeClient(ScriptResourceClient* client) 74 { 75 ASSERT(m_client == client); 76 m_client = 0; 77 } 78 79 // Called by PendingScript when data arrives from the network. 80 void notifyAppendData(ScriptResource*); 81 void notifyFinished(Resource*); 82 83 // Called by ScriptStreamingTask when it has streamed all data to V8 and V8 84 // has processed it. 85 void streamingComplete(); 86 87 static void removeSmallScriptThresholdForTesting() 88 { 89 kSmallScriptThreshold = 0; 90 } 91 92 static size_t smallScriptThreshold() { return kSmallScriptThreshold; } 93 94 private: 95 // Scripts whose first data chunk is smaller than this constant won't be 96 // streamed. Non-const for testing. 97 static size_t kSmallScriptThreshold; 98 99 ScriptStreamer(ScriptResource*, v8::ScriptCompiler::StreamedSource::Encoding, PendingScript::Type); 100 101 void notifyFinishedToClient(); 102 103 static const char* startedStreamingHistogramName(PendingScript::Type); 104 105 static bool startStreamingInternal(PendingScript&, Settings*, ScriptState*, PendingScript::Type); 106 107 // This pointer is weak. If PendingScript and its Resource are deleted 108 // before ScriptStreamer, PendingScript will notify ScriptStreamer of its 109 // deletion by calling cancel(). 110 ScriptResource* m_resource; 111 // Whether ScriptStreamer is detached from the Resource. In those cases, the 112 // script data is not needed any more, and the client won't get notified 113 // when the loading and streaming are done. 114 bool m_detached; 115 116 SourceStream* m_stream; 117 v8::ScriptCompiler::StreamedSource m_source; 118 ScriptResourceClient* m_client; 119 v8::ScriptCompiler::ScriptStreamingTask* m_task; 120 bool m_loadingFinished; // Whether loading from the network is done. 121 bool m_parsingFinished; // Whether the V8 side processing is done. 122 bool m_firstDataChunkReceived; 123 124 // Whether the script source code should be retrieved from the Resource 125 // instead of the ScriptStreamer. 126 bool m_streamingSuppressed; 127 128 // What kind of cached data V8 produces during streaming. 129 unsigned m_cachedDataType; 130 131 // For recording metrics for different types of scripts separately. 132 PendingScript::Type m_scriptType; 133 }; 134 135 } // namespace blink 136 137 #endif // ScriptStreamer_h 138