1 // Copyright 2015 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 "testing/gtest/include/gtest/gtest.h" 6 #include "testing/js_embedder_test.h" 7 8 namespace { 9 10 const double kExpected0 = 6.0; 11 const double kExpected1 = 7.0; 12 const double kExpected2 = 8.0; 13 14 const wchar_t kScript0[] = L"fred = 6"; 15 const wchar_t kScript1[] = L"fred = 7"; 16 const wchar_t kScript2[] = L"fred = 8"; 17 18 } // namespace 19 20 class FXJSV8EmbedderTest : public JSEmbedderTest { 21 public: 22 void ExecuteInCurrentContext(const WideString& script) { 23 FXJSErr error; 24 int sts = engine()->Execute(script, &error); 25 EXPECT_EQ(0, sts); 26 } 27 void CheckAssignmentInCurrentContext(double expected) { 28 v8::Local<v8::Object> This = engine()->GetThisObj(); 29 v8::Local<v8::Value> fred = engine()->GetObjectProperty(This, L"fred"); 30 EXPECT_TRUE(fred->IsNumber()); 31 EXPECT_EQ(expected, engine()->ToDouble(fred)); 32 } 33 }; 34 35 TEST_F(FXJSV8EmbedderTest, Getters) { 36 v8::Isolate::Scope isolate_scope(isolate()); 37 v8::HandleScope handle_scope(isolate()); 38 v8::Context::Scope context_scope(GetV8Context()); 39 40 ExecuteInCurrentContext(WideString(kScript1)); 41 CheckAssignmentInCurrentContext(kExpected1); 42 } 43 44 TEST_F(FXJSV8EmbedderTest, MultipleEngines) { 45 v8::Isolate::Scope isolate_scope(isolate()); 46 v8::HandleScope handle_scope(isolate()); 47 48 CFXJS_Engine engine1(isolate()); 49 engine1.InitializeEngine(); 50 51 CFXJS_Engine engine2(isolate()); 52 engine2.InitializeEngine(); 53 54 v8::Context::Scope context_scope(GetV8Context()); 55 ExecuteInCurrentContext(WideString(kScript0)); 56 CheckAssignmentInCurrentContext(kExpected0); 57 58 { 59 v8::Local<v8::Context> context1 = engine1.NewLocalContext(); 60 v8::Context::Scope context_scope1(context1); 61 ExecuteInCurrentContext(WideString(kScript1)); 62 CheckAssignmentInCurrentContext(kExpected1); 63 } 64 65 engine1.ReleaseEngine(); 66 67 { 68 v8::Local<v8::Context> context2 = engine2.NewLocalContext(); 69 v8::Context::Scope context_scope2(context2); 70 ExecuteInCurrentContext(WideString(kScript2)); 71 CheckAssignmentInCurrentContext(kExpected2); 72 } 73 74 engine2.ReleaseEngine(); 75 CheckAssignmentInCurrentContext(kExpected0); 76 } 77 78 TEST_F(FXJSV8EmbedderTest, EmptyLocal) { 79 v8::Isolate::Scope isolate_scope(isolate()); 80 v8::HandleScope handle_scope(isolate()); 81 v8::Context::Scope context_scope(GetV8Context()); 82 83 v8::Local<v8::Value> empty; 84 EXPECT_FALSE(engine()->ToBoolean(empty)); 85 EXPECT_EQ(0, engine()->ToInt32(empty)); 86 EXPECT_EQ(0.0, engine()->ToDouble(empty)); 87 EXPECT_EQ(L"", engine()->ToWideString(empty)); 88 EXPECT_TRUE(engine()->ToObject(empty).IsEmpty()); 89 EXPECT_TRUE(engine()->ToArray(empty).IsEmpty()); 90 } 91 92 TEST_F(FXJSV8EmbedderTest, NewNull) { 93 v8::Isolate::Scope isolate_scope(isolate()); 94 v8::HandleScope handle_scope(isolate()); 95 v8::Context::Scope context_scope(GetV8Context()); 96 97 auto nullz = engine()->NewNull(); 98 EXPECT_FALSE(engine()->ToBoolean(nullz)); 99 EXPECT_EQ(0, engine()->ToInt32(nullz)); 100 EXPECT_EQ(0.0, engine()->ToDouble(nullz)); 101 EXPECT_EQ(L"null", engine()->ToWideString(nullz)); 102 EXPECT_TRUE(engine()->ToObject(nullz).IsEmpty()); 103 EXPECT_TRUE(engine()->ToArray(nullz).IsEmpty()); 104 } 105 106 TEST_F(FXJSV8EmbedderTest, NewUndefined) { 107 v8::Isolate::Scope isolate_scope(isolate()); 108 v8::HandleScope handle_scope(isolate()); 109 v8::Context::Scope context_scope(GetV8Context()); 110 111 auto undef = engine()->NewUndefined(); 112 EXPECT_FALSE(engine()->ToBoolean(undef)); 113 EXPECT_EQ(0, engine()->ToInt32(undef)); 114 EXPECT_TRUE(std::isnan(engine()->ToDouble(undef))); 115 EXPECT_EQ(L"undefined", engine()->ToWideString(undef)); 116 EXPECT_TRUE(engine()->ToObject(undef).IsEmpty()); 117 EXPECT_TRUE(engine()->ToArray(undef).IsEmpty()); 118 } 119 120 TEST_F(FXJSV8EmbedderTest, NewBoolean) { 121 v8::Isolate::Scope isolate_scope(isolate()); 122 v8::HandleScope handle_scope(isolate()); 123 v8::Context::Scope context_scope(GetV8Context()); 124 125 auto boolz = engine()->NewBoolean(true); 126 EXPECT_TRUE(engine()->ToBoolean(boolz)); 127 EXPECT_EQ(1, engine()->ToInt32(boolz)); 128 EXPECT_EQ(1.0, engine()->ToDouble(boolz)); 129 EXPECT_EQ(L"true", engine()->ToWideString(boolz)); 130 EXPECT_TRUE(engine()->ToObject(boolz).IsEmpty()); 131 EXPECT_TRUE(engine()->ToArray(boolz).IsEmpty()); 132 } 133 134 TEST_F(FXJSV8EmbedderTest, NewNumber) { 135 v8::Isolate::Scope isolate_scope(isolate()); 136 v8::HandleScope handle_scope(isolate()); 137 v8::Context::Scope context_scope(GetV8Context()); 138 139 auto num = engine()->NewNumber(42.1); 140 EXPECT_TRUE(engine()->ToBoolean(num)); 141 EXPECT_EQ(42, engine()->ToInt32(num)); 142 EXPECT_EQ(42.1, engine()->ToDouble(num)); 143 EXPECT_EQ(L"42.1", engine()->ToWideString(num)); 144 EXPECT_TRUE(engine()->ToObject(num).IsEmpty()); 145 EXPECT_TRUE(engine()->ToArray(num).IsEmpty()); 146 } 147 148 TEST_F(FXJSV8EmbedderTest, NewString) { 149 v8::Isolate::Scope isolate_scope(isolate()); 150 v8::HandleScope handle_scope(isolate()); 151 v8::Context::Scope context_scope(GetV8Context()); 152 153 auto str = engine()->NewString(L"123"); 154 EXPECT_TRUE(engine()->ToBoolean(str)); 155 EXPECT_EQ(123, engine()->ToInt32(str)); 156 EXPECT_EQ(123, engine()->ToDouble(str)); 157 EXPECT_EQ(L"123", engine()->ToWideString(str)); 158 EXPECT_TRUE(engine()->ToObject(str).IsEmpty()); 159 EXPECT_TRUE(engine()->ToArray(str).IsEmpty()); 160 } 161 162 TEST_F(FXJSV8EmbedderTest, NewDate) { 163 v8::Isolate::Scope isolate_scope(isolate()); 164 v8::HandleScope handle_scope(isolate()); 165 v8::Context::Scope context_scope(GetV8Context()); 166 167 auto date = engine()->NewDate(1111111111); 168 EXPECT_TRUE(engine()->ToBoolean(date)); 169 EXPECT_EQ(1111111111, engine()->ToInt32(date)); 170 EXPECT_EQ(1111111111.0, engine()->ToDouble(date)); 171 EXPECT_NE(L"", engine()->ToWideString(date)); // exact format varies. 172 EXPECT_TRUE(engine()->ToObject(date)->IsObject()); 173 EXPECT_TRUE(engine()->ToArray(date).IsEmpty()); 174 } 175 176 TEST_F(FXJSV8EmbedderTest, NewArray) { 177 v8::Isolate::Scope isolate_scope(isolate()); 178 v8::HandleScope handle_scope(isolate()); 179 v8::Context::Scope context_scope(GetV8Context()); 180 181 auto array = engine()->NewArray(); 182 EXPECT_EQ(0u, engine()->GetArrayLength(array)); 183 EXPECT_FALSE(engine()->GetArrayElement(array, 2).IsEmpty()); 184 EXPECT_TRUE(engine()->GetArrayElement(array, 2)->IsUndefined()); 185 EXPECT_EQ(0u, engine()->GetArrayLength(array)); 186 187 engine()->PutArrayElement(array, 3, engine()->NewNumber(12)); 188 EXPECT_FALSE(engine()->GetArrayElement(array, 2).IsEmpty()); 189 EXPECT_TRUE(engine()->GetArrayElement(array, 2)->IsUndefined()); 190 EXPECT_FALSE(engine()->GetArrayElement(array, 3).IsEmpty()); 191 EXPECT_TRUE(engine()->GetArrayElement(array, 3)->IsNumber()); 192 EXPECT_EQ(4u, engine()->GetArrayLength(array)); 193 194 EXPECT_TRUE(engine()->ToBoolean(array)); 195 EXPECT_EQ(0, engine()->ToInt32(array)); 196 double d = engine()->ToDouble(array); 197 EXPECT_NE(d, d); // i.e. NaN. 198 EXPECT_EQ(L",,,12", engine()->ToWideString(array)); 199 EXPECT_TRUE(engine()->ToObject(array)->IsObject()); 200 EXPECT_TRUE(engine()->ToArray(array)->IsArray()); 201 } 202 203 TEST_F(FXJSV8EmbedderTest, NewObject) { 204 v8::Isolate::Scope isolate_scope(isolate()); 205 v8::HandleScope handle_scope(isolate()); 206 v8::Context::Scope context_scope(GetV8Context()); 207 208 auto object = engine()->NewFxDynamicObj(-1); 209 ASSERT_FALSE(object.IsEmpty()); 210 EXPECT_EQ(0u, engine()->GetObjectPropertyNames(object).size()); 211 EXPECT_FALSE(engine()->GetObjectProperty(object, L"clams").IsEmpty()); 212 EXPECT_TRUE(engine()->GetObjectProperty(object, L"clams")->IsUndefined()); 213 EXPECT_EQ(0u, engine()->GetObjectPropertyNames(object).size()); 214 215 engine()->PutObjectProperty(object, L"clams", engine()->NewNumber(12)); 216 EXPECT_FALSE(engine()->GetObjectProperty(object, L"clams").IsEmpty()); 217 EXPECT_TRUE(engine()->GetObjectProperty(object, L"clams")->IsNumber()); 218 EXPECT_EQ(1u, engine()->GetObjectPropertyNames(object).size()); 219 EXPECT_EQ(L"clams", engine()->GetObjectPropertyNames(object)[0]); 220 221 EXPECT_TRUE(engine()->ToBoolean(object)); 222 EXPECT_EQ(0, engine()->ToInt32(object)); 223 double d = engine()->ToDouble(object); 224 EXPECT_NE(d, d); // i.e. NaN. 225 EXPECT_EQ(L"[object Object]", engine()->ToWideString(object)); 226 EXPECT_TRUE(engine()->ToObject(object)->IsObject()); 227 EXPECT_TRUE(engine()->ToArray(object).IsEmpty()); 228 } 229