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 #include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/single_thread_task_runner.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
13 #include "third_party/blink/public/platform/platform.h"
14 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
15 #include "third_party/blink/public/platform/web_url_loader.h"
16 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
17 #include "third_party/blink/public/platform/web_url_request_extra_data.h"
18 #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
19 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
20 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
21 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
22 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
23 #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
24 #include "third_party/blink/renderer/core/frame/settings.h"
25 #include "third_party/blink/renderer/core/script/classic_pending_script.h"
26 #include "third_party/blink/renderer/core/script/classic_script.h"
27 #include "third_party/blink/renderer/core/script/mock_script_element_base.h"
28 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
29 #include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
30 #include "third_party/blink/renderer/platform/heap/handle.h"
31 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
32 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
33 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
34 #include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
35 #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
36 #include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
37 #include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
38 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
39 #include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h"
40 #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
41 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
42 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
43 #include "v8/include/v8.h"
44 
45 namespace blink {
46 
47 namespace {
48 
49 class TestResourceClient final : public GarbageCollected<TestResourceClient>,
50                                  public ResourceClient {
51 
52  public:
TestResourceClient()53   TestResourceClient() : finished_(false) {}
Finished() const54   bool Finished() const { return finished_; }
55 
DataReceived(Resource *,const char *,size_t)56   void DataReceived(Resource*,
57                     const char* /* data */,
58                     size_t /* length */) override {}
NotifyFinished(Resource *)59   void NotifyFinished(Resource*) override { finished_ = true; }
60 
61   // Name for debugging, e.g. shown in memory-infra.
DebugName() const62   String DebugName() const override { return "TestResourceClient"; }
63 
64  private:
65   bool finished_;
66 };
67 
68 // TODO(leszeks): This class has a similar class in resource_loader_test.cc,
69 // the two should probably share the same class.
70 class NoopLoaderFactory final : public ResourceFetcher::LoaderFactory {
CreateURLLoader(const ResourceRequest & request,const ResourceLoaderOptions & options,scoped_refptr<base::SingleThreadTaskRunner>,scoped_refptr<base::SingleThreadTaskRunner>)71   std::unique_ptr<WebURLLoader> CreateURLLoader(
72       const ResourceRequest& request,
73       const ResourceLoaderOptions& options,
74       scoped_refptr<base::SingleThreadTaskRunner>,
75       scoped_refptr<base::SingleThreadTaskRunner>) override {
76     return std::make_unique<NoopWebURLLoader>();
77   }
CreateCodeCacheLoader()78   std::unique_ptr<WebCodeCacheLoader> CreateCodeCacheLoader() override {
79     return Platform::Current()->CreateCodeCacheLoader();
80   }
81 
82   class NoopWebURLLoader final : public WebURLLoader {
83    public:
84     ~NoopWebURLLoader() override = default;
LoadSynchronously(std::unique_ptr<network::ResourceRequest> request,scoped_refptr<WebURLRequestExtraData> url_request_extra_data,int requestor_id,bool pass_response_pipe_to_client,bool no_mime_sniffing,base::TimeDelta timeout_interval,WebURLLoaderClient *,WebURLResponse &,base::Optional<WebURLError> &,WebData &,int64_t & encoded_data_length,int64_t & encoded_body_length,WebBlobInfo & downloaded_blob,std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper> resource_load_info_notifier_wrapper)85     void LoadSynchronously(
86         std::unique_ptr<network::ResourceRequest> request,
87         scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
88         int requestor_id,
89         bool pass_response_pipe_to_client,
90         bool no_mime_sniffing,
91         base::TimeDelta timeout_interval,
92         WebURLLoaderClient*,
93         WebURLResponse&,
94         base::Optional<WebURLError>&,
95         WebData&,
96         int64_t& encoded_data_length,
97         int64_t& encoded_body_length,
98         WebBlobInfo& downloaded_blob,
99         std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
100             resource_load_info_notifier_wrapper) override {
101       NOTREACHED();
102     }
LoadAsynchronously(std::unique_ptr<network::ResourceRequest> request,scoped_refptr<WebURLRequestExtraData> url_request_extra_data,int requestor_id,bool no_mime_sniffing,std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper> resource_load_info_notifier_wrapper,WebURLLoaderClient *)103     void LoadAsynchronously(
104         std::unique_ptr<network::ResourceRequest> request,
105         scoped_refptr<WebURLRequestExtraData> url_request_extra_data,
106         int requestor_id,
107         bool no_mime_sniffing,
108         std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
109             resource_load_info_notifier_wrapper,
110         WebURLLoaderClient*) override {}
SetDefersLoading(WebURLLoader::DeferType)111     void SetDefersLoading(WebURLLoader::DeferType) override {}
DidChangePriority(WebURLRequest::Priority,int)112     void DidChangePriority(WebURLRequest::Priority, int) override {
113       NOTREACHED();
114     }
GetTaskRunnerForBodyLoader()115     scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForBodyLoader()
116         override {
117       return base::MakeRefCounted<scheduler::FakeTaskRunner>();
118     }
119   };
120 };
121 
122 class ScriptStreamingTest : public testing::Test {
123  public:
ScriptStreamingTest()124   ScriptStreamingTest()
125       : url_("http://www.streaming-test.com/"),
126         freezable_task_runner_(platform_->test_task_runner()),
127         unfreezable_task_runner_(platform_->test_task_runner()) {
128     auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
129     FetchContext* context = MakeGarbageCollected<MockFetchContext>();
130     auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
131         properties->MakeDetachable(), context, freezable_task_runner_,
132         unfreezable_task_runner_, MakeGarbageCollected<NoopLoaderFactory>(),
133         MakeGarbageCollected<MockContextLifecycleNotifier>()));
134 
135     ResourceRequest request(url_);
136     request.SetRequestContext(mojom::blink::RequestContextType::SCRIPT);
137 
138     resource_client_ = MakeGarbageCollected<TestResourceClient>();
139     FetchParameters params = FetchParameters::CreateForTest(std::move(request));
140     resource_ = ScriptResource::Fetch(params, fetcher, resource_client_,
141                                       ScriptResource::kAllowStreaming);
142     resource_->AddClient(resource_client_, freezable_task_runner_.get());
143 
144     ScriptStreamer::SetSmallScriptThresholdForTesting(0);
145 
146     ResourceResponse response(url_);
147     response.SetHttpStatusCode(200);
148     resource_->SetResponse(response);
149 
150     resource_->Loader()->DidReceiveResponse(WrappedResourceResponse(response));
151     resource_->Loader()->DidStartLoadingResponseBody(
152         std::move(data_pipe_.consumer_handle));
153   }
154 
GetScriptSourceCode() const155   ScriptSourceCode GetScriptSourceCode() const {
156     ScriptStreamer* streamer = resource_->TakeStreamer();
157     if (streamer) {
158       if (streamer->IsStreamingSuppressed()) {
159         return ScriptSourceCode(nullptr, resource_,
160                                 streamer->StreamingSuppressedReason());
161       }
162       return ScriptSourceCode(streamer, resource_,
163                               ScriptStreamer::NotStreamingReason::kInvalid);
164     }
165     return ScriptSourceCode(nullptr, resource_, resource_->NoStreamerReason());
166   }
167 
GetSettings() const168   Settings* GetSettings() const {
169     return &dummy_page_holder_->GetPage().GetSettings();
170   }
171 
172  protected:
AppendData(const char * data)173   void AppendData(const char* data) {
174     uint32_t data_len = strlen(data);
175     MojoResult result = data_pipe_.producer_handle->WriteData(
176         data, &data_len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
177     EXPECT_EQ(result, MOJO_RESULT_OK);
178 
179     // Yield control to the background thread, so that V8 gets a chance to
180     // process the data before the main thread adds more. Note that we
181     // cannot fully control in what kind of chunks the data is passed to V8
182     // (if V8 is not requesting more data between two appendData calls, it
183     // will get both chunks together).
184     test::YieldCurrentThread();
185   }
186 
AppendPadding()187   void AppendPadding() {
188     for (int i = 0; i < 10; ++i) {
189       AppendData(
190           " /* this is padding to make the script long enough, so "
191           "that V8's buffer gets filled and it starts processing "
192           "the data */ ");
193     }
194   }
195 
Finish()196   void Finish() {
197     resource_->Loader()->DidFinishLoading(base::TimeTicks(), 0, 0, 0, false);
198     data_pipe_.producer_handle.reset();
199     resource_->SetStatus(ResourceStatus::kCached);
200   }
201 
ProcessTasksUntilStreamingComplete()202   void ProcessTasksUntilStreamingComplete() { platform_->RunUntilIdle(); }
203 
204   ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
205       platform_;
206 
207   KURL url_;
208   scoped_refptr<base::SingleThreadTaskRunner> freezable_task_runner_;
209   scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner_;
210 
211   Persistent<TestResourceClient> resource_client_;
212   Persistent<ScriptResource> resource_;
213   mojo::DataPipe data_pipe_;
214 
215   std::unique_ptr<DummyPageHolder> dummy_page_holder_;
216 };
217 
218 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
219 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_CompilingStreamedScript)220 TEST_F(ScriptStreamingTest, DISABLED_CompilingStreamedScript) {
221   // Test that we can successfully compile a streamed script.
222   V8TestingScope scope;
223 
224   AppendData("function foo() {");
225   AppendPadding();
226   AppendData("return 5; }");
227   AppendPadding();
228   AppendData("foo();");
229   EXPECT_FALSE(resource_client_->Finished());
230   Finish();
231 
232   // Process tasks on the main thread until the streaming background thread
233   // has completed its tasks.
234   ProcessTasksUntilStreamingComplete();
235   EXPECT_TRUE(resource_client_->Finished());
236   ScriptSourceCode source_code = GetScriptSourceCode();
237   EXPECT_TRUE(source_code.Streamer());
238   v8::TryCatch try_catch(scope.GetIsolate());
239   v8::Local<v8::Script> script;
240   v8::ScriptCompiler::CompileOptions compile_options;
241   V8CodeCache::ProduceCacheOptions produce_cache_options;
242   v8::ScriptCompiler::NoCacheReason no_cache_reason;
243   std::tie(compile_options, produce_cache_options, no_cache_reason) =
244       V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
245                                      source_code);
246   EXPECT_TRUE(V8ScriptRunner::CompileScript(
247                   scope.GetScriptState(), source_code,
248                   SanitizeScriptErrors::kDoNotSanitize, compile_options,
249                   no_cache_reason, ReferrerScriptInfo())
250                   .ToLocal(&script));
251   EXPECT_FALSE(try_catch.HasCaught());
252 }
253 
254 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
255 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_CompilingStreamedScriptWithParseError)256 TEST_F(ScriptStreamingTest, DISABLED_CompilingStreamedScriptWithParseError) {
257   // Test that scripts with parse errors are handled properly. In those cases,
258   // V8 stops reading the network stream: make sure we handle it gracefully.
259   V8TestingScope scope;
260   AppendData("function foo() {");
261   AppendData("this is the part which will be a parse error");
262   // V8 won't realize the parse error until it actually starts parsing the
263   // script, and this happens only when its buffer is filled.
264   AppendPadding();
265 
266   EXPECT_FALSE(resource_client_->Finished());
267   Finish();
268 
269   // Process tasks on the main thread until the streaming background thread
270   // has completed its tasks.
271   ProcessTasksUntilStreamingComplete();
272   EXPECT_TRUE(resource_client_->Finished());
273   ScriptSourceCode source_code = GetScriptSourceCode();
274   EXPECT_TRUE(source_code.Streamer());
275   v8::TryCatch try_catch(scope.GetIsolate());
276   v8::Local<v8::Script> script;
277   v8::ScriptCompiler::CompileOptions compile_options;
278   V8CodeCache::ProduceCacheOptions produce_cache_options;
279   v8::ScriptCompiler::NoCacheReason no_cache_reason;
280   std::tie(compile_options, produce_cache_options, no_cache_reason) =
281       V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
282                                      source_code);
283   EXPECT_FALSE(V8ScriptRunner::CompileScript(
284                    scope.GetScriptState(), source_code,
285                    SanitizeScriptErrors::kDoNotSanitize, compile_options,
286                    no_cache_reason, ReferrerScriptInfo())
287                    .ToLocal(&script));
288   EXPECT_TRUE(try_catch.HasCaught());
289 }
290 
291 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
292 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_CancellingStreaming)293 TEST_F(ScriptStreamingTest, DISABLED_CancellingStreaming) {
294   // Test that the upper layers (PendingScript and up) can be ramped down
295   // while streaming is ongoing, and ScriptStreamer handles it gracefully.
296   V8TestingScope scope;
297   AppendData("function foo() {");
298 
299   // In general, we cannot control what the background thread is doing
300   // (whether it's parsing or waiting for more data). In this test, we have
301   // given it so little data that it's surely waiting for more.
302 
303   // Simulate cancelling the network load (e.g., because the user navigated
304   // away).
305   EXPECT_FALSE(resource_client_->Finished());
306   resource_ = nullptr;
307 
308   // The V8 side will complete too. This should not crash. We don't receive
309   // any results from the streaming and the client doesn't get notified.
310   ProcessTasksUntilStreamingComplete();
311   EXPECT_FALSE(resource_client_->Finished());
312 }
313 
314 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
315 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_DataAfterDisposingPendingScript)316 TEST_F(ScriptStreamingTest, DISABLED_DataAfterDisposingPendingScript) {
317   // Test that the upper layers (PendingScript and up) can be ramped down
318   // before streaming is started, and ScriptStreamer handles it gracefully.
319   V8TestingScope scope;
320 
321   // In general, we cannot control what the background thread is doing
322   // (whether it's parsing or waiting for more data). In this test, we have
323   // given it so little data that it's surely waiting for more.
324 
325   EXPECT_FALSE(resource_client_->Finished());
326 
327   // Keep the resource alive
328   Persistent<ScriptResource> resource = resource_;
329 
330   // Simulate cancelling the network load (e.g., because the user navigated
331   // away).
332   resource_ = nullptr;
333 
334   // Make sure the streaming starts.
335   AppendData("function foo() {");
336   AppendPadding();
337   resource.Clear();
338 
339   // The V8 side will complete too. This should not crash. We don't receive
340   // any results from the streaming and the client doesn't get notified.
341   ProcessTasksUntilStreamingComplete();
342   EXPECT_FALSE(resource_client_->Finished());
343 }
344 
345 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
346 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_SuppressingStreaming)347 TEST_F(ScriptStreamingTest, DISABLED_SuppressingStreaming) {
348   // If we notice before streaming that there is a code cache, streaming
349   // is suppressed (V8 doesn't parse while the script is loading), and the
350   // upper layer (ScriptResourceClient) should get a notification when the
351   // script is loaded.
352   V8TestingScope scope;
353 
354   SingleCachedMetadataHandler* cache_handler = resource_->CacheHandler();
355   EXPECT_TRUE(cache_handler);
356   cache_handler->DisableSendToPlatformForTesting();
357   cache_handler->SetCachedMetadata(V8CodeCache::TagForCodeCache(cache_handler),
358                                    reinterpret_cast<const uint8_t*>("X"), 1);
359 
360   AppendData("function foo() {");
361   AppendPadding();
362   Finish();
363   ProcessTasksUntilStreamingComplete();
364   EXPECT_TRUE(resource_client_->Finished());
365 
366   ScriptSourceCode source_code = GetScriptSourceCode();
367   // ScriptSourceCode doesn't refer to the streamer, since we have suppressed
368   // the streaming and resumed the non-streaming code path for script
369   // compilation.
370   EXPECT_FALSE(source_code.Streamer());
371 }
372 
373 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
374 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_EmptyScripts)375 TEST_F(ScriptStreamingTest, DISABLED_EmptyScripts) {
376   // Empty scripts should also be streamed properly, that is, the upper layer
377   // (ScriptResourceClient) should be notified when an empty script has been
378   // loaded.
379   V8TestingScope scope;
380 
381   // Finish the script without sending any data.
382   Finish();
383   ProcessTasksUntilStreamingComplete();
384   EXPECT_TRUE(resource_client_->Finished());
385 
386   ScriptSourceCode source_code = GetScriptSourceCode();
387   EXPECT_FALSE(source_code.Streamer());
388 }
389 
390 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
391 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_SmallScripts)392 TEST_F(ScriptStreamingTest, DISABLED_SmallScripts) {
393   // Small scripts shouldn't be streamed.
394   V8TestingScope scope;
395   ScriptStreamer::SetSmallScriptThresholdForTesting(100);
396 
397   AppendData("function foo() { }");
398 
399   Finish();
400   ProcessTasksUntilStreamingComplete();
401   EXPECT_TRUE(resource_client_->Finished());
402 
403   ScriptSourceCode source_code = GetScriptSourceCode();
404   EXPECT_FALSE(source_code.Streamer());
405 }
406 
407 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
408 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_ScriptsWithSmallFirstChunk)409 TEST_F(ScriptStreamingTest, DISABLED_ScriptsWithSmallFirstChunk) {
410   // If a script is long enough, if should be streamed, even if the first data
411   // chunk is small.
412   V8TestingScope scope;
413   ScriptStreamer::SetSmallScriptThresholdForTesting(100);
414 
415   // This is the first data chunk which is small.
416   AppendData("function foo() { }");
417   AppendPadding();
418   AppendPadding();
419   AppendPadding();
420 
421   Finish();
422 
423   ProcessTasksUntilStreamingComplete();
424   EXPECT_TRUE(resource_client_->Finished());
425   ScriptSourceCode source_code = GetScriptSourceCode();
426   EXPECT_TRUE(source_code.Streamer());
427   v8::TryCatch try_catch(scope.GetIsolate());
428   v8::Local<v8::Script> script;
429   v8::ScriptCompiler::CompileOptions compile_options;
430   V8CodeCache::ProduceCacheOptions produce_cache_options;
431   v8::ScriptCompiler::NoCacheReason no_cache_reason;
432   std::tie(compile_options, produce_cache_options, no_cache_reason) =
433       V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
434                                      source_code);
435   EXPECT_TRUE(V8ScriptRunner::CompileScript(
436                   scope.GetScriptState(), source_code,
437                   SanitizeScriptErrors::kDoNotSanitize, compile_options,
438                   no_cache_reason, ReferrerScriptInfo())
439                   .ToLocal(&script));
440   EXPECT_FALSE(try_catch.HasCaught());
441 }
442 
443 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
444 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_EncodingChanges)445 TEST_F(ScriptStreamingTest, DISABLED_EncodingChanges) {
446   // It's possible that the encoding of the Resource changes after we start
447   // loading it.
448   V8TestingScope scope;
449   resource_->SetEncodingForTest("windows-1252");
450 
451   resource_->SetEncodingForTest("UTF-8");
452   // \xec\x92\x81 are the raw bytes for \uc481.
453   AppendData(
454       "function foo() { var foob\xec\x92\x81r = 13; return foob\xec\x92\x81r; "
455       "} foo();");
456 
457   Finish();
458 
459   ProcessTasksUntilStreamingComplete();
460   EXPECT_TRUE(resource_client_->Finished());
461   ScriptSourceCode source_code = GetScriptSourceCode();
462   EXPECT_TRUE(source_code.Streamer());
463   v8::TryCatch try_catch(scope.GetIsolate());
464   v8::Local<v8::Script> script;
465   v8::ScriptCompiler::CompileOptions compile_options;
466   V8CodeCache::ProduceCacheOptions produce_cache_options;
467   v8::ScriptCompiler::NoCacheReason no_cache_reason;
468   std::tie(compile_options, produce_cache_options, no_cache_reason) =
469       V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
470                                      source_code);
471   EXPECT_TRUE(V8ScriptRunner::CompileScript(
472                   scope.GetScriptState(), source_code,
473                   SanitizeScriptErrors::kDoNotSanitize, compile_options,
474                   no_cache_reason, ReferrerScriptInfo())
475                   .ToLocal(&script));
476   EXPECT_FALSE(try_catch.HasCaught());
477 }
478 
479 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
480 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_EncodingFromBOM)481 TEST_F(ScriptStreamingTest, DISABLED_EncodingFromBOM) {
482   // Byte order marks should be removed before giving the data to V8. They
483   // will also affect encoding detection.
484   V8TestingScope scope;
485 
486   // This encoding is wrong on purpose.
487   resource_->SetEncodingForTest("windows-1252");
488 
489   // \xef\xbb\xbf is the UTF-8 byte order mark. \xec\x92\x81 are the raw bytes
490   // for \uc481.
491   AppendData(
492       "\xef\xbb\xbf function foo() { var foob\xec\x92\x81r = 13; return "
493       "foob\xec\x92\x81r; } foo();");
494 
495   Finish();
496   ProcessTasksUntilStreamingComplete();
497   EXPECT_TRUE(resource_client_->Finished());
498   ScriptSourceCode source_code = GetScriptSourceCode();
499   EXPECT_TRUE(source_code.Streamer());
500   v8::TryCatch try_catch(scope.GetIsolate());
501   v8::Local<v8::Script> script;
502   v8::ScriptCompiler::CompileOptions compile_options;
503   V8CodeCache::ProduceCacheOptions produce_cache_options;
504   v8::ScriptCompiler::NoCacheReason no_cache_reason;
505   std::tie(compile_options, produce_cache_options, no_cache_reason) =
506       V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions::kDefault,
507                                      source_code);
508   EXPECT_TRUE(V8ScriptRunner::CompileScript(
509                   scope.GetScriptState(), source_code,
510                   SanitizeScriptErrors::kDoNotSanitize, compile_options,
511                   no_cache_reason, ReferrerScriptInfo())
512                   .ToLocal(&script));
513   EXPECT_FALSE(try_catch.HasCaught());
514 }
515 
516 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
517 // currently unable to block and wait for the script streaming thread.
518 // A test for crbug.com/711703. Should not crash.
TEST_F(ScriptStreamingTest,DISABLED_GarbageCollectDuringStreaming)519 TEST_F(ScriptStreamingTest, DISABLED_GarbageCollectDuringStreaming) {
520   V8TestingScope scope;
521 
522   EXPECT_FALSE(resource_client_->Finished());
523 
524   resource_ = nullptr;
525   ThreadState::Current()->CollectAllGarbageForTesting(
526       BlinkGC::kNoHeapPointersOnStack);
527 }
528 
529 // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
530 // currently unable to block and wait for the script streaming thread.
TEST_F(ScriptStreamingTest,DISABLED_ResourceSetRevalidatingRequest)531 TEST_F(ScriptStreamingTest, DISABLED_ResourceSetRevalidatingRequest) {
532   V8TestingScope scope;
533 
534   // Kick the streaming off.
535   AppendData("function foo() {");
536   AppendPadding();
537   AppendData("}");
538   Finish();
539   ProcessTasksUntilStreamingComplete();
540 
541   // Should be done streaming by now.
542   EXPECT_TRUE(resource_->HasStreamer());
543   EXPECT_FALSE(resource_->HasRunningStreamer());
544 
545   ResourceRequest request(resource_->Url());
546   resource_->SetRevalidatingRequest(request);
547 
548   // Now there shouldn't be a streamer at all, and the reason should be
549   // "kRevalidate".
550   EXPECT_FALSE(resource_->HasStreamer());
551   EXPECT_EQ(resource_->NoStreamerReason(),
552             ScriptStreamer::NotStreamingReason::kRevalidate);
553 }
554 
555 }  // namespace
556 
557 }  // namespace blink
558