summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc
blob: 3f69e6542e1575b746ee9d2ba1f4859e1de1da06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright 2017 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.

#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"

#include "build/build_config.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/workers/worker_thread_test_helper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h"

namespace blink {

// On debug builds, Oilpan contains checks that will fail if a persistent handle
// is destroyed on the wrong thread.
TEST(SerializedScriptValueThreadedTest,
     SafeDestructionIfSendingThreadKeepsAlive) {
  V8TestingScope scope;

  // Start a worker.
  WorkerReportingProxy proxy;
  WorkerThreadForTest worker_thread(nullptr, proxy);
  ParentExecutionContextTaskRunners* parent_execution_context_task_runners =
      ParentExecutionContextTaskRunners::Create(&scope.GetDocument());
  worker_thread.StartWithSourceCode(scope.GetDocument().GetSecurityOrigin(),
                                    "/* no worker script */",
                                    parent_execution_context_task_runners);

  // Create a serialized script value that contains transferred array buffer
  // contents.
  DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(1, 1);
  Transferables transferables;
  transferables.array_buffers.push_back(array_buffer);
  SerializedScriptValue::SerializeOptions options;
  options.transferables = &transferables;
  scoped_refptr<SerializedScriptValue> serialized =
      SerializedScriptValue::Serialize(
          scope.GetIsolate(),
          ToV8(array_buffer, scope.GetContext()->Global(), scope.GetIsolate()),
          options, ASSERT_NO_EXCEPTION);
  EXPECT_TRUE(serialized);
  EXPECT_TRUE(array_buffer->IsNeutered());

  // Deserialize the serialized value on the worker.
  // Intentionally keep a reference on this thread while this occurs.
  worker_thread.GetWorkerBackingThread().BackingThread().PostTask(
      FROM_HERE,
      CrossThreadBind(
          [](WorkerThread* worker_thread,
             scoped_refptr<SerializedScriptValue> serialized) {
            WorkerOrWorkletScriptController* script =
                worker_thread->GlobalScope()->ScriptController();
            EXPECT_TRUE(script->IsContextInitialized());
            ScriptState::Scope worker_scope(script->GetScriptState());
            SerializedScriptValue::Unpack(serialized)
                ->Deserialize(worker_thread->GetIsolate());

            // Make sure this thread's references in the Oilpan heap are dropped
            // before the main thread continues.
            ThreadState::Current()->CollectAllGarbage();
          },
          CrossThreadUnretained(&worker_thread), serialized));

  // Wait for a subsequent task on the worker to finish, to ensure that the
  // references held by the task are dropped.
  WaitableEvent done;
  worker_thread.GetWorkerBackingThread().BackingThread().PostTask(
      FROM_HERE,
      CrossThreadBind(&WaitableEvent::Signal, CrossThreadUnretained(&done)));
  done.Wait();

  // Now destroy the value on the main thread.
  EXPECT_TRUE(serialized->HasOneRef());
  serialized = nullptr;

  // Finally, shut down the worker thread.
  worker_thread.Terminate();
  worker_thread.WaitForShutdownForTesting();
}

}  // namespace blink