Home | History | Annotate | Download | only in fxjs
      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