1 // Copyright 2018 PDFium 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 "fxjs/cfxjs_engine.h"
6
7 #include <memory>
8
9 #include "fxjs/cfx_v8_unittest.h"
10 #include "fxjs/cjs_object.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/base/ptr_util.h"
13
14 class FXJSEngineUnitTest : public FXV8UnitTest {
15 public:
16 FXJSEngineUnitTest() = default;
17 ~FXJSEngineUnitTest() override = default;
18
SetUp()19 void SetUp() override {
20 FXV8UnitTest::SetUp();
21 FXJS_Initialize(1, isolate());
22 engine_ = pdfium::MakeUnique<CFXJS_Engine>(isolate());
23 }
24
TearDown()25 void TearDown() override { FXJS_Release(); }
26
engine() const27 CFXJS_Engine* engine() const { return engine_.get(); }
28
29 private:
30 std::unique_ptr<CFXJS_Engine> engine_;
31 };
32
33 static bool perm_created = false;
34 static bool perm_destroyed = false;
35 static bool temp_created = false;
36 static bool temp_destroyed = false;
37
TEST_F(FXJSEngineUnitTest,GC)38 TEST_F(FXJSEngineUnitTest, GC) {
39 v8::Isolate::Scope isolate_scope(isolate());
40 v8::HandleScope handle_scope(isolate());
41
42 // Object: 0
43 engine()->DefineObj(
44 "perm", FXJSOBJTYPE_DYNAMIC,
45 [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
46 pEngine->SetObjectPrivate(obj,
47 pdfium::MakeUnique<CJS_Object>(obj, nullptr));
48 perm_created = true;
49 },
50 [](v8::Local<v8::Object> obj) {
51 perm_destroyed = true;
52 CFXJS_Engine::SetObjectPrivate(obj, nullptr);
53 });
54
55 // Object: 1
56 engine()->DefineObj(
57 "temp", FXJSOBJTYPE_DYNAMIC,
58 [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
59 pEngine->SetObjectPrivate(obj,
60 pdfium::MakeUnique<CJS_Object>(obj, nullptr));
61 temp_created = true;
62 },
63 [](v8::Local<v8::Object> obj) {
64 temp_destroyed = true;
65 CFXJS_Engine::SetObjectPrivate(obj, nullptr);
66 });
67
68 engine()->InitializeEngine();
69
70 v8::Context::Scope context_scope(engine()->GetV8Context());
71 v8::Local<v8::Object> perm =
72 engine()->NewFXJSBoundObject(0, FXJSOBJTYPE_DYNAMIC);
73 EXPECT_FALSE(perm.IsEmpty());
74 EXPECT_TRUE(perm_created);
75 EXPECT_FALSE(perm_destroyed);
76
77 {
78 v8::HandleScope inner_handle_scope(isolate());
79 v8::Local<v8::Object> temp =
80 engine()->NewFXJSBoundObject(1, FXJSOBJTYPE_DYNAMIC);
81 EXPECT_FALSE(temp.IsEmpty());
82 EXPECT_TRUE(temp_created);
83 EXPECT_FALSE(temp_destroyed);
84 }
85
86 Optional<IJS_Runtime::JS_Error> err = engine()->Execute(L"gc();");
87 EXPECT_FALSE(err);
88
89 EXPECT_TRUE(perm_created);
90 EXPECT_FALSE(perm_destroyed);
91 EXPECT_TRUE(temp_created);
92 // TODO(tsepez): temp_destroyed should be true, but it isnt.
93 // EXPECT_TRUE(temp_destroyed);
94
95 engine()->ReleaseEngine();
96 EXPECT_TRUE(perm_created);
97 EXPECT_TRUE(perm_destroyed);
98 EXPECT_TRUE(temp_created);
99 EXPECT_TRUE(temp_destroyed);
100 }
101