// Copyright 2018 PDFium 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 "fxjs/cfxjs_engine.h" #include <memory> #include "fxjs/cfx_v8_unittest.h" #include "fxjs/cjs_object.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/base/ptr_util.h" class FXJSEngineUnitTest : public FXV8UnitTest { public: FXJSEngineUnitTest() = default; ~FXJSEngineUnitTest() override = default; void SetUp() override { FXV8UnitTest::SetUp(); FXJS_Initialize(1, isolate()); engine_ = pdfium::MakeUnique<CFXJS_Engine>(isolate()); } void TearDown() override { FXJS_Release(); } CFXJS_Engine* engine() const { return engine_.get(); } private: std::unique_ptr<CFXJS_Engine> engine_; }; static bool perm_created = false; static bool perm_destroyed = false; static bool temp_created = false; static bool temp_destroyed = false; TEST_F(FXJSEngineUnitTest, GC) { v8::Isolate::Scope isolate_scope(isolate()); v8::HandleScope handle_scope(isolate()); // Object: 0 engine()->DefineObj("perm", FXJSOBJTYPE_DYNAMIC, [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) { pEngine->SetObjectPrivate( obj, pdfium::MakeUnique<CJS_Object>(obj, nullptr)); perm_created = true; }, [](v8::Local<v8::Object> obj) { perm_destroyed = true; CFXJS_Engine::SetObjectPrivate(obj, nullptr); }); // Object: 1 engine()->DefineObj("temp", FXJSOBJTYPE_DYNAMIC, [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) { pEngine->SetObjectPrivate( obj, pdfium::MakeUnique<CJS_Object>(obj, nullptr)); temp_created = true; }, [](v8::Local<v8::Object> obj) { temp_destroyed = true; CFXJS_Engine::SetObjectPrivate(obj, nullptr); }); engine()->InitializeEngine(); v8::Context::Scope context_scope(engine()->GetV8Context()); v8::Local<v8::Object> perm = engine()->NewFXJSBoundObject(0, false); EXPECT_FALSE(perm.IsEmpty()); EXPECT_TRUE(perm_created); EXPECT_FALSE(perm_destroyed); { v8::HandleScope inner_handle_scope(isolate()); v8::Local<v8::Object> temp = engine()->NewFXJSBoundObject(1, false); EXPECT_FALSE(temp.IsEmpty()); EXPECT_TRUE(temp_created); EXPECT_FALSE(temp_destroyed); } Optional<IJS_Runtime::JS_Error> err = engine()->Execute(L"gc();"); EXPECT_FALSE(err); EXPECT_TRUE(perm_created); EXPECT_FALSE(perm_destroyed); EXPECT_TRUE(temp_created); // TODO(tsepez): temp_destroyed should be true, but it isnt. // EXPECT_TRUE(temp_destroyed); engine()->ReleaseEngine(); EXPECT_TRUE(perm_created); EXPECT_TRUE(perm_destroyed); EXPECT_TRUE(temp_created); EXPECT_TRUE(temp_destroyed); }