data_object_builder_unittest.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2017 The Chromium 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. #include "gin/data_object_builder.h"
  5. #include "base/bind.h"
  6. #include "base/logging.h"
  7. #include "gin/dictionary.h"
  8. #include "gin/public/isolate_holder.h"
  9. #include "gin/test/v8_test.h"
  10. #include "v8/include/v8-context.h"
  11. #include "v8/include/v8-function.h"
  12. namespace gin {
  13. namespace {
  14. using DataObjectBuilderTest = V8Test;
  15. // It should create ordinary data properties.
  16. TEST_F(DataObjectBuilderTest, CreatesDataProperties) {
  17. v8::Isolate* isolate = instance_->isolate();
  18. v8::HandleScope handle_scope(isolate);
  19. v8::Local<v8::Context> context = context_.Get(isolate);
  20. v8::Local<v8::Object> object =
  21. DataObjectBuilder(isolate).Set("key", 42).Build();
  22. ASSERT_TRUE(object->HasOwnProperty(context, StringToSymbol(isolate, "key"))
  23. .ToChecked());
  24. v8::Local<v8::Value> descriptor_object;
  25. ASSERT_TRUE(
  26. object->GetOwnPropertyDescriptor(context, StringToSymbol(isolate, "key"))
  27. .ToLocal(&descriptor_object));
  28. gin::Dictionary descriptor(isolate, descriptor_object.As<v8::Object>());
  29. int32_t value = 0;
  30. ASSERT_TRUE(descriptor.Get("value", &value));
  31. EXPECT_EQ(42, value);
  32. bool writable = false;
  33. ASSERT_TRUE(descriptor.Get("writable", &writable));
  34. EXPECT_TRUE(writable);
  35. bool enumerable = false;
  36. ASSERT_TRUE(descriptor.Get("enumerable", &enumerable));
  37. EXPECT_TRUE(enumerable);
  38. bool configurable = false;
  39. ASSERT_TRUE(descriptor.Get("configurable", &configurable));
  40. EXPECT_TRUE(configurable);
  41. }
  42. // It should not invoke setters on the prototype chain.
  43. TEST_F(DataObjectBuilderTest, DoesNotInvokeSetters) {
  44. v8::Isolate* isolate = instance_->isolate();
  45. v8::HandleScope handle_scope(isolate);
  46. v8::Local<v8::Context> context = context_.Get(isolate);
  47. // Install a setter on the object prototype.
  48. v8::Local<v8::Value> object_constructor;
  49. ASSERT_TRUE(context->Global()
  50. ->Get(context, StringToSymbol(isolate, "Object"))
  51. .ToLocal(&object_constructor));
  52. v8::Local<v8::Value> object_prototype;
  53. ASSERT_TRUE(object_constructor.As<v8::Function>()
  54. ->Get(context, StringToSymbol(isolate, "prototype"))
  55. .ToLocal(&object_prototype));
  56. ASSERT_TRUE(
  57. object_prototype.As<v8::Object>()
  58. ->SetAccessor(context, StringToSymbol(isolate, "key"),
  59. [](v8::Local<v8::Name>,
  60. const v8::PropertyCallbackInfo<v8::Value>&) {},
  61. [](v8::Local<v8::Name>, v8::Local<v8::Value>,
  62. const v8::PropertyCallbackInfo<void>&) {
  63. ADD_FAILURE() << "setter should not be invoked";
  64. })
  65. .ToChecked());
  66. // Create an object.
  67. DataObjectBuilder(isolate).Set("key", 42).Build();
  68. }
  69. // The internal handle is cleared when the builder is finished.
  70. // This makes the class harder to abuse, so that its methods cannot be used
  71. // after something may have modified the object in unexpected ways.
  72. #if DCHECK_IS_ON()
  73. TEST_F(DataObjectBuilderTest, UnusableAfterBuild) {
  74. v8::Isolate* isolate = instance_->isolate();
  75. v8::HandleScope handle_scope(isolate);
  76. DataObjectBuilder builder(isolate);
  77. EXPECT_FALSE(builder.Build().IsEmpty());
  78. bool has_dcheck_failure = false;
  79. logging::ScopedLogAssertHandler handler(base::BindRepeating(
  80. [](bool* flag, const char* file, int line, base::StringPiece message,
  81. base::StringPiece stack_trace) { *flag = true; },
  82. base::Unretained(&has_dcheck_failure)));
  83. builder.Build();
  84. EXPECT_TRUE(has_dcheck_failure);
  85. }
  86. #endif // DCHECK_IS_ON()
  87. // As is the normal behaviour of CreateDataProperty, new data properties should
  88. // replace existing ones. Since no non-configurable ones are present, nor should
  89. // the object be non-extensible, this should work.
  90. TEST_F(DataObjectBuilderTest, ReplacesExistingProperties) {
  91. v8::Isolate* isolate = instance_->isolate();
  92. v8::HandleScope handle_scope(isolate);
  93. v8::Local<v8::Object> object =
  94. DataObjectBuilder(isolate).Set("value", 42).Set("value", 55).Build();
  95. gin::Dictionary dictionary(isolate, object);
  96. int32_t value;
  97. ASSERT_TRUE(dictionary.Get("value", &value));
  98. EXPECT_EQ(55, value);
  99. }
  100. // It should work for array indices, too.
  101. TEST_F(DataObjectBuilderTest, CreatesDataPropertiesForIndices) {
  102. v8::Isolate* isolate = instance_->isolate();
  103. v8::HandleScope handle_scope(isolate);
  104. v8::Local<v8::Context> context = context_.Get(isolate);
  105. v8::Local<v8::Object> object = DataObjectBuilder(isolate)
  106. .Set(42, base::StringPiece("forty-two"))
  107. .Build();
  108. ASSERT_TRUE(object->HasOwnProperty(context, 42).ToChecked());
  109. v8::Local<v8::Value> descriptor_object;
  110. ASSERT_TRUE(
  111. object->GetOwnPropertyDescriptor(context, StringToSymbol(isolate, "42"))
  112. .ToLocal(&descriptor_object));
  113. gin::Dictionary descriptor(isolate, descriptor_object.As<v8::Object>());
  114. std::string value;
  115. ASSERT_TRUE(descriptor.Get("value", &value));
  116. EXPECT_EQ("forty-two", value);
  117. bool writable = false;
  118. ASSERT_TRUE(descriptor.Get("writable", &writable));
  119. EXPECT_TRUE(writable);
  120. bool enumerable = false;
  121. ASSERT_TRUE(descriptor.Get("enumerable", &enumerable));
  122. EXPECT_TRUE(enumerable);
  123. bool configurable = false;
  124. ASSERT_TRUE(descriptor.Get("configurable", &configurable));
  125. EXPECT_TRUE(configurable);
  126. }
  127. } // namespace
  128. } // namespace gin