Index: test/cctest/test-api-accessors.cc |
diff --git a/test/cctest/test-api-accessors.cc b/test/cctest/test-api-accessors.cc |
index cda16cdbcbce8c27997dbc4b3be0153e9f3ce569..e9773e918df6284be78e0473b585617bd46aa2f1 100644 |
--- a/test/cctest/test-api-accessors.cc |
+++ b/test/cctest/test-api-accessors.cc |
@@ -4,9 +4,9 @@ |
#include "test/cctest/cctest.h" |
-#include "include/v8.h" |
#include "include/v8-experimental.h" |
- |
+#include "include/v8.h" |
+#include "src/api.h" |
namespace i = v8::internal; |
@@ -111,3 +111,139 @@ TEST(FastAccessors) { |
"}", |
31415); |
} |
+ |
+// The goal is to avoid the callback. |
+static void UnreachableCallback( |
+ const v8::FunctionCallbackInfo<v8::Value>& info) { |
+ UNREACHABLE(); |
+} |
+ |
+TEST(CachedAccessor) { |
+ // Crankshaft support for fast accessors is not implemented; crankshafted |
+ // code uses the slow accessor which breaks this test's expectations. |
+ v8::internal::FLAG_always_opt = false; |
+ LocalContext env; |
+ v8::Isolate* isolate = env->GetIsolate(); |
+ v8::HandleScope scope(isolate); |
+ |
+ // Create 'foo' class, with a hidden property. |
+ v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); |
+ |
+ v8::Local<v8::Private> priv = |
+ v8::Private::ForApi(isolate, v8_str("Foo#draft")); |
+ |
+ foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache( |
+ isolate, UnreachableCallback, |
+ priv, v8::Local<v8::Value>())); |
+ |
+ // Create 'obj', instance of 'foo'. |
+ v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); |
+ |
+ // Install the private property on the instance. |
+ CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv, |
+ v8::Undefined(isolate)) |
+ .FromJust()); |
+ |
+ CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
+ |
+ // Access cached accessor. |
+ ExpectUndefined("obj.draft"); |
+ |
+ // Set hidden property. |
+ CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv, |
+ v8_str("Shhh, I'm private!")) |
+ .FromJust()); |
+ |
+ ExpectString("obj.draft", "Shhh, I'm private!"); |
+ |
+ // Stress the accessor to use the IC. |
+ ExpectString( |
+ "var result = '';" |
+ "for (var i = 0; i < 10; ++i) { " |
+ " result = obj.draft; " |
+ "} " |
+ "result; ", |
+ "Shhh, I'm private!"); |
+} |
+ |
+TEST(CachedAccessorCrankshaft) { |
+ i::FLAG_allow_natives_syntax = true; |
+ // v8::internal::FLAG_always_opt = false; |
+ LocalContext env; |
+ v8::Isolate* isolate = env->GetIsolate(); |
+ v8::HandleScope scope(isolate); |
+ |
+ // Create 'foo' class, with a hidden property. |
+ v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate); |
+ v8::Local<v8::Private> priv = |
+ v8::Private::ForApi(isolate, v8_str("Foo#draft")); |
+ |
+ // Install the private property on the template. |
+ // foo->SetPrivate(priv, v8::Undefined(isolate)); |
+ |
+ foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache( |
+ isolate, UnreachableCallback, |
+ priv, v8::Local<v8::Value>())); |
+ |
+ // Create 'obj', instance of 'foo'. |
+ v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked(); |
+ |
+ // Install the private property on the instance. |
+ CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv, |
+ v8::Undefined(isolate)) |
+ .FromJust()); |
+ |
+ CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust()); |
+ |
+ // Access surrogate accessor. |
+ ExpectUndefined("obj.draft"); |
+ |
+ // Set hidden property. |
+ CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123)) |
+ .FromJust()); |
+ |
+ // Test ICs. |
+ CompileRun( |
+ "function f() {" |
+ " var x;" |
+ " for (var i = 0; i < 100; i++) {" |
+ " x = obj.draft;" |
+ " }" |
+ " return x;" |
+ "}"); |
+ |
+ ExpectInt32("f()", 123); |
+ |
+ // Reset hidden property. |
+ CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456)) |
+ .FromJust()); |
+ |
+ // Test Crankshaft. |
+ CompileRun("%OptimizeFunctionOnNextCall(f);"); |
+ |
+ ExpectInt32("f()", 456); |
+ |
+ CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456)) |
+ .FromJust()); |
+ // Test non-global ICs. |
+ CompileRun( |
+ "function g() {" |
+ " var x = obj;" |
+ " var r = 0;" |
+ " for (var i = 0; i < 100; i++) {" |
+ " r = x.draft;" |
+ " }" |
+ " return r;" |
+ "}"); |
+ |
+ ExpectInt32("g()", 456); |
+ |
+ // Reset hidden property. |
+ CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789)) |
+ .FromJust()); |
+ |
+ // Test non-global access in Crankshaft. |
+ CompileRun("%OptimizeFunctionOnNextCall(g);"); |
+ |
+ ExpectInt32("g()", 789); |
+} |