blob: 2390472594f4cab8a43d11c1d908e6654767c68d [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ScriptStreamer_h
#define ScriptStreamer_h
#include <memory>
#include "core/CoreExport.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/Noncopyable.h"
#include "platform/wtf/text/WTFString.h"
#include "v8/include/v8.h"
namespace blink {
class PendingScript;
class Resource;
class ScriptResource;
class ScriptState;
class Settings;
class SourceStream;
class WebTaskRunner;
// ScriptStreamer streams incomplete script data to V8 so that it can be parsed
// while it's loaded. PendingScript holds a reference to ScriptStreamer. At the
// moment, ScriptStreamer is only used for parser blocking scripts; this means
// that the Document stays stable and no other scripts are executing while we're
// streaming. It is possible, though, that Document and the PendingScript are
// destroyed while the streaming is in progress, and ScriptStreamer handles it
// gracefully.
class CORE_EXPORT ScriptStreamer final
: public GarbageCollectedFinalized<ScriptStreamer> {
WTF_MAKE_NONCOPYABLE(ScriptStreamer);
public:
enum Type { kParsingBlocking, kDeferred, kAsync };
~ScriptStreamer();
DECLARE_TRACE();
// Launches a task (on a background thread) which will stream the given
// PendingScript into V8 as it loads.
static void StartStreaming(PendingScript*,
Type,
Settings*,
ScriptState*,
RefPtr<WebTaskRunner>);
// Returns false if we cannot stream the given encoding.
static bool ConvertEncoding(const char* encoding_name,
v8::ScriptCompiler::StreamedSource::Encoding*);
bool IsFinished() const;
v8::ScriptCompiler::StreamedSource* Source() { return source_.get(); }
ScriptResource* GetResource() const { return resource_; }
// Called when the script is not needed any more (e.g., loading was
// cancelled). After calling cancel, PendingScript can drop its reference to
// ScriptStreamer, and ScriptStreamer takes care of eventually deleting
// itself (after the V8 side has finished too).
void Cancel();
// When the streaming is suppressed, the data is not given to V8, but
// ScriptStreamer still watches the resource load and notifies the upper
// layers when loading is finished. It is used in situations when we have
// started streaming but then we detect we don't want to stream (e.g., when
// we have the code cache for the script) and we still want to parse and
// execute it when it has finished loading.
void SuppressStreaming();
bool StreamingSuppressed() const { return streaming_suppressed_; }
v8::ScriptCompiler::CompileOptions GetCompileOptions() const {
return compile_options_;
}
// Called by PendingScript when data arrives from the network.
void NotifyAppendData(ScriptResource*);
void NotifyFinished(Resource*);
// Called by ScriptStreamingTask when it has streamed all data to V8 and V8
// has processed it.
void StreamingCompleteOnBackgroundThread();
v8::ScriptCompiler::StreamedSource::Encoding GetEncoding() const {
return encoding_;
}
const String& ScriptURLString() const { return script_url_string_; }
unsigned long ScriptResourceIdentifier() const {
return script_resource_identifier_;
}
static void SetSmallScriptThresholdForTesting(size_t threshold) {
small_script_threshold_ = threshold;
}
static size_t SmallScriptThreshold() { return small_script_threshold_; }
private:
// Scripts whose first data chunk is smaller than this constant won't be
// streamed. Non-const for testing.
static size_t small_script_threshold_;
static ScriptStreamer* Create(
PendingScript* script,
Type script_type,
ScriptState* script_state,
v8::ScriptCompiler::CompileOptions compile_options,
RefPtr<WebTaskRunner> loading_task_runner) {
return new ScriptStreamer(script, script_type, script_state,
compile_options, std::move(loading_task_runner));
}
ScriptStreamer(PendingScript*,
Type,
ScriptState*,
v8::ScriptCompiler::CompileOptions,
RefPtr<WebTaskRunner>);
void StreamingComplete();
void NotifyFinishedToClient();
static bool StartStreamingInternal(PendingScript*,
Type,
Settings*,
ScriptState*,
RefPtr<WebTaskRunner>);
Member<PendingScript> pending_script_;
// This pointer is weak. If PendingScript and its Resource are deleted
// before ScriptStreamer, PendingScript will notify ScriptStreamer of its
// deletion by calling cancel().
Member<ScriptResource> resource_;
// Whether ScriptStreamer is detached from the Resource. In those cases, the
// script data is not needed any more, and the client won't get notified
// when the loading and streaming are done.
bool detached_;
SourceStream* stream_;
std::unique_ptr<v8::ScriptCompiler::StreamedSource> source_;
bool loading_finished_; // Whether loading from the network is done.
bool parsing_finished_; // Whether the V8 side processing is done.
// Whether we have received enough data to start the streaming.
bool have_enough_data_for_streaming_;
// Whether the script source code should be retrieved from the Resource
// instead of the ScriptStreamer.
bool streaming_suppressed_;
// What kind of cached data V8 produces during streaming.
v8::ScriptCompiler::CompileOptions compile_options_;
RefPtr<ScriptState> script_state_;
// For recording metrics for different types of scripts separately.
Type script_type_;
// Keep the script URL string for event tracing.
const String script_url_string_;
// Keep the script resource dentifier for event tracing.
const unsigned long script_resource_identifier_;
// Encoding of the streamed script. Saved for sanity checking purposes.
v8::ScriptCompiler::StreamedSource::Encoding encoding_;
RefPtr<WebTaskRunner> loading_task_runner_;
};
} // namespace blink
#endif // ScriptStreamer_h