Home | History | Annotate | Download | only in cctest
      1 // Copyright 2015 the V8 project 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 "test/cctest/cctest.h"
      6 
      7 #include "include/v8.h"
      8 #include "include/v8-experimental.h"
      9 
     10 
     11 namespace i = v8::internal;
     12 
     13 static void CppAccessor42(const v8::FunctionCallbackInfo<v8::Value>& info) {
     14   info.GetReturnValue().Set(42);
     15 }
     16 
     17 
     18 static void CppAccessor41(const v8::FunctionCallbackInfo<v8::Value>& info) {
     19   info.GetReturnValue().Set(41);
     20 }
     21 
     22 
     23 v8::experimental::FastAccessorBuilder* FastAccessor(v8::Isolate* isolate) {
     24   auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
     25   builder->ReturnValue(builder->IntegerConstant(41));
     26   return builder;
     27 }
     28 
     29 
     30 TEST(FastAccessors) {
     31   v8::Isolate* isolate = CcTest::isolate();
     32   v8::HandleScope scope(isolate);
     33   LocalContext env;
     34 
     35   // We emulate Embedder-created DOM Node instances. Specifically:
     36   // - 'parent': FunctionTemplate ~= DOM Node superclass
     37   // - 'child':  FunctionTemplate ~= a specific DOM node type, like a <div />
     38   //
     39   // We'll install both a C++-based and a JS-based accessor on the parent,
     40   // and expect it to be callable on the child.
     41 
     42   // Setup the parent template ( =~ DOM Node w/ accessors).
     43   v8::Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
     44   {
     45     auto signature = v8::Signature::New(isolate, parent);
     46 
     47     // cpp accessor as "firstChild":
     48     parent->PrototypeTemplate()->SetAccessorProperty(
     49         v8_str("firstChild"),
     50         v8::FunctionTemplate::New(isolate, CppAccessor42,
     51                                   v8::Local<v8::Value>(), signature));
     52 
     53     // JS accessor as "firstChildRaw":
     54     parent->PrototypeTemplate()->SetAccessorProperty(
     55         v8_str("firstChildRaw"),
     56         v8::FunctionTemplate::NewWithFastHandler(
     57             isolate, CppAccessor41, FastAccessor(isolate),
     58             v8::Local<v8::Value>(), signature));
     59   }
     60 
     61   // Setup child object ( =~ a specific DOM Node, e.g. a <div> ).
     62   // Also, make a creation function on the global object, so we can access it
     63   // in a test.
     64   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
     65   child->Inherit(parent);
     66   CHECK(env->Global()
     67             ->Set(env.local(), v8_str("Node"),
     68                   child->GetFunction(env.local()).ToLocalChecked())
     69             .IsJust());
     70 
     71   // Setup done: Let's test it:
     72 
     73   // The simple case: Run it once.
     74   ExpectInt32("var n = new Node(); n.firstChild", 42);
     75   ExpectInt32("var n = new Node(); n.firstChildRaw", 41);
     76 
     77   // Run them in a loop. This will likely trigger the optimizing compiler:
     78   ExpectInt32(
     79       "var m = new Node(); "
     80       "var sum = 0; "
     81       "for (var i = 0; i < 10; ++i) { "
     82       "  sum += m.firstChild; "
     83       "  sum += m.firstChildRaw; "
     84       "}; "
     85       "sum;",
     86       10 * (42 + 41));
     87 
     88   // Obtain the accessor and call it via apply on the Node:
     89   ExpectInt32(
     90       "var n = new Node(); "
     91       "var g = Object.getOwnPropertyDescriptor("
     92       "    n.__proto__.__proto__, 'firstChild')['get']; "
     93       "g.apply(n);",
     94       42);
     95   ExpectInt32(
     96       "var n = new Node(); "
     97       "var g = Object.getOwnPropertyDescriptor("
     98       "    n.__proto__.__proto__, 'firstChildRaw')['get']; "
     99       "g.apply(n);",
    100       41);
    101 
    102   ExpectInt32(
    103       "var n = new Node();"
    104       "var g = Object.getOwnPropertyDescriptor("
    105       "    n.__proto__.__proto__, 'firstChildRaw')['get'];"
    106       "try {"
    107       "  var f = { firstChildRaw: '51' };"
    108       "  g.apply(f);"
    109       "} catch(e) {"
    110       "  31415;"
    111       "}",
    112       31415);
    113 }
    114