#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include <atomic>
#include <memory>
#include <utility>
#include "base/check_op.h"
#include "base/containers/heap_array.h"
#include "base/containers/span.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/sequence_checker.h"
#include "base/state_transitions.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
#include "base/types/pass_key.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "mojo/public/cpp/system/wait.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/page/v8_compile_hints_histograms.h"
#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/script/script_type.mojom-shared.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_compile_hints_common.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_compile_hints_consumer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_compile_hints_for_streaming.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_compile_hints_producer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_local_compile_hints_consumer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/cross_thread_handle.h"
#include "third_party/blink/renderer/platform/heap/cross_thread_persistent.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_mojo.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
namespace WTF {
template <>
struct CrossThreadCopier<mojo_base::BigBuffer> { … };
}
namespace blink {
namespace {
v8::ScriptType ScriptTypeForStreamingTask(ScriptResource* script_resource) { … }
}
class SourceStream : public v8::ScriptCompiler::ExternalSourceStream { … };
std::tuple<ScriptStreamer*, ScriptStreamer::NotStreamingReason>
ScriptStreamer::TakeFrom(ScriptResource* script_resource,
mojom::blink::ScriptType expected_type) { … }
namespace {
enum class StreamedBoolean { … };
void RecordStartedStreamingHistogram(ScriptSchedulingType type,
bool did_use_streamer) { … }
void RecordNotStreamingReasonHistogram(
ScriptSchedulingType type,
ScriptStreamer::NotStreamingReason reason) { … }
}
void ScriptStreamer::RecordStreamingHistogram(
ScriptSchedulingType type,
bool can_use_streamer,
ScriptStreamer::NotStreamingReason reason) { … }
bool ScriptStreamer::ConvertEncoding(
const char* encoding_name,
v8::ScriptCompiler::StreamedSource::Encoding* encoding) { … }
v8_compile_hints::V8LocalCompileHintsConsumer*
ResourceScriptStreamer::GetV8LocalCompileHintsConsumerForTest() const { … }
bool ResourceScriptStreamer::IsStreamingStarted() const { … }
bool ResourceScriptStreamer::IsStreamingSuppressed() const { … }
bool ResourceScriptStreamer::IsLoaded() const { … }
bool ResourceScriptStreamer::CanStartStreaming() const { … }
bool ResourceScriptStreamer::IsFinished() const { … }
bool ResourceScriptStreamer::IsClientDetached() const { … }
void ResourceScriptStreamer::StreamingCompleteOnBackgroundThread(
LoadingState state) { … }
void ResourceScriptStreamer::Cancel() { … }
void ResourceScriptStreamer::SuppressStreaming(NotStreamingReason reason) { … }
void ResourceScriptStreamer::RunScriptStreamingTask(
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
ResourceScriptStreamer* streamer,
SourceStream* stream) { … }
bool ResourceScriptStreamer::TryStartStreamingTask() { … }
v8::ScriptType ResourceScriptStreamer::GetScriptType() const { … }
ResourceScriptStreamer::ResourceScriptStreamer(
ScriptResource* script_resource,
mojo::ScopedDataPipeConsumerHandle data_pipe,
ResponseBodyLoaderClient* response_body_loader_client,
std::unique_ptr<TextResourceDecoder> decoder,
scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner)
: … { … }
void ResourceScriptStreamer::OnDataPipeReadable(
MojoResult result,
const mojo::HandleSignalsState& state) { … }
ResourceScriptStreamer::~ResourceScriptStreamer() = default;
void ResourceScriptStreamer::Prefinalize() { … }
void ResourceScriptStreamer::Trace(Visitor* visitor) const { … }
void ResourceScriptStreamer::StreamingComplete(LoadingState loading_state) { … }
void ResourceScriptStreamer::LoadCompleteWithoutStreaming(
LoadingState state,
NotStreamingReason no_streaming_reason) { … }
void ResourceScriptStreamer::SendClientLoadFinishedCallback() { … }
void ResourceScriptStreamer::AdvanceLoadingState(LoadingState new_state) { … }
void ResourceScriptStreamer::CheckState() const { … }
class InlineSourceStream final
: public v8::ScriptCompiler::ExternalSourceStream { … };
BackgroundInlineScriptStreamer::BackgroundInlineScriptStreamer(
v8::Isolate* isolate,
const String& text,
v8::ScriptCompiler::CompileOptions compile_options) { … }
void BackgroundInlineScriptStreamer::Run() { … }
v8::ScriptCompiler::StreamedSource* BackgroundInlineScriptStreamer::Source(
v8::ScriptType expected_type) { … }
InlineScriptStreamer* InlineScriptStreamer::From(
scoped_refptr<BackgroundInlineScriptStreamer> streamer) { … }
namespace {
enum class BackgroundProcessorState { … };
#if DCHECK_IS_ON()
std::ostream& operator<<(std::ostream& o, const BackgroundProcessorState& s) { … }
#endif
std::unique_ptr<v8::ScriptCompiler::ConsumeCodeCacheTask>
MaybeCreateConsumeCodeCacheTask(std::optional<mojo_base::BigBuffer>& big_buffer,
const String& encoding,
v8::Isolate* isolate,
bool& has_code_cache,
v8::ScriptType script_type) { … }
std::unique_ptr<v8_compile_hints::CompileHintsForStreaming>
BuildCompileHintsForStreaming(
v8_compile_hints::CompileHintsForStreaming::Builder& builder,
std::optional<mojo_base::BigBuffer>& big_buffer,
const String& encoding) { … }
}
BackgroundResourceScriptStreamer::Result::Result(
String decoded_data,
std::unique_ptr<ParkableStringImpl::SecureDigest> digest,
std::unique_ptr<v8::ScriptCompiler::StreamedSource> streamed_source)
: … { … }
BackgroundResourceScriptStreamer::Result::Result(
String decoded_data,
std::unique_ptr<ParkableStringImpl::SecureDigest> digest,
std::unique_ptr<v8::ScriptCompiler::ConsumeCodeCacheTask>
consume_code_cache_task)
: … { … }
class BackgroundResourceScriptStreamer::BackgroundProcessor final
: public BackgroundResponseProcessor { … };
class BackgroundResourceScriptStreamer::BackgroundProcessorFactory final
: public BackgroundResponseProcessorFactory { … };
BackgroundResourceScriptStreamer::BackgroundProcessor::BackgroundProcessor(
v8::ScriptType script_type,
const String script_url_string,
uint64_t script_resource_identifier,
v8::Isolate* isolate,
WTF::TextEncoding encoding,
std::unique_ptr<v8_compile_hints::CompileHintsForStreaming::Builder>
compile_hints_builder,
CrossThreadWeakHandle<BackgroundResourceScriptStreamer> streamer_handle)
: … { … }
BackgroundResourceScriptStreamer::BackgroundProcessor::~BackgroundProcessor() { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::SetState(
BackgroundProcessorState state) { … }
bool BackgroundResourceScriptStreamer::BackgroundProcessor::
MaybeStartProcessingResponse(
network::mojom::URLResponseHeadPtr& head,
mojo::ScopedDataPipeConsumerHandle& body,
std::optional<mojo_base::BigBuffer>& cached_metadata,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
Client* client) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::OnDataPipeReadable(
MojoResult ready_result,
const mojo::HandleSignalsState& ready_state) { … }
bool BackgroundResourceScriptStreamer::BackgroundProcessor::
TryStartStreamingTask(MojoResult result,
const mojo::HandleSignalsState& state) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::
RunScriptStreamingTask(
const String script_url_string,
uint64_t script_resource_identifier,
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask>
script_streaming_task,
std::unique_ptr<v8::ScriptCompiler::StreamedSource> streamed_source,
SourceStream* source_stream_ptr,
ScriptDecoderPtr script_decoder,
std::unique_ptr<v8_compile_hints::CompileHintsForStreaming>
compile_hints,
base::WeakPtr<BackgroundProcessor> background_processor_weak_ptr) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::OnFinishStreaming(
std::unique_ptr<v8::ScriptCompiler::StreamedSource> streamed_source,
ScriptDecoderPtr script_decoder,
ScriptDecoder::Result result) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::
RunConsumingCodeCacheTask(
const String script_url_string,
uint64_t script_resource_identifier,
std::unique_ptr<v8::ScriptCompiler::ConsumeCodeCacheTask>
consume_code_cache_task,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
mojo_base::BigBuffer cached_metadata,
base::WeakPtr<BackgroundProcessor> background_processor_weak_ptr,
const uint64_t trace_id) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::
OnFinishCodeCacheConsumer(
std::unique_ptr<v8::ScriptCompiler::ConsumeCodeCacheTask>
consume_code_cache_task,
mojo_base::BigBuffer cached_metadata) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::
OnFinishScriptDecode(ScriptDecoder::Result result) { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::
OnFinishCodeCacheConsumerScriptDecode() { … }
bool BackgroundResourceScriptStreamer::BackgroundProcessor::
IsStreamingSuppressed() { … }
void BackgroundResourceScriptStreamer::BackgroundProcessor::SuppressStreaming(
NotStreamingReason reason) { … }
BackgroundResourceScriptStreamer::BackgroundResourceScriptStreamer(
ScriptResource* script_resource)
: … { … }
BackgroundResourceScriptStreamer::~BackgroundResourceScriptStreamer() = default;
void BackgroundResourceScriptStreamer::Trace(Visitor* visitor) const { … }
v8::ScriptCompiler::StreamedSource* BackgroundResourceScriptStreamer::Source(
v8::ScriptType expected_type) { … }
std::unique_ptr<BackgroundResponseProcessorFactory>
BackgroundResourceScriptStreamer::CreateBackgroundResponseProcessorFactory() { … }
ParkableString BackgroundResourceScriptStreamer::TakeDecodedData() { … }
std::unique_ptr<v8::ScriptCompiler::ConsumeCodeCacheTask>
BackgroundResourceScriptStreamer::TakeConsumeCodeCacheTask() { … }
v8::ScriptType BackgroundResourceScriptStreamer::GetScriptType() const { … }
void BackgroundResourceScriptStreamer::OnResult(
std::unique_ptr<Result> result,
NotStreamingReason suppressed_reason) { … }
}