Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 | } |