| OLD | NEW | 
|    1 // Copyright 2015 the V8 project authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 // TODO(jochen): Remove this after the setting is turned on globally. |    5 // TODO(jochen): Remove this after the setting is turned on globally. | 
|    6 #define V8_IMMINENT_DEPRECATION_WARNINGS |    6 #define V8_IMMINENT_DEPRECATION_WARNINGS | 
|    7  |    7  | 
|    8 #include "test/cctest/cctest.h" |    8 #include "test/cctest/cctest.h" | 
|    9  |    9  | 
|   10 #include "include/v8.h" |   10 #include "include/v8.h" | 
 |   11 #include "src/compiler/pipeline.h" | 
 |   12 #include "src/compiler/raw-machine-assembler.h" | 
|   11  |   13  | 
|   12  |   14  | 
|   13 #ifdef V8_JS_ACCESSORS |   15 #ifdef V8_FAST_ACCESSORS | 
 |   16 namespace i = v8::internal; | 
 |   17  | 
|   14 static void CppAccessor(const v8::FunctionCallbackInfo<v8::Value>& info) { |   18 static void CppAccessor(const v8::FunctionCallbackInfo<v8::Value>& info) { | 
|   15   info.GetReturnValue().Set(42); |   19   info.GetReturnValue().Set(42); | 
|   16 } |   20 } | 
|   17  |   21  | 
|   18 static const char* JsAccessor = |   22  | 
|   19     "function firstChildJS(value) { return 41; }; firstChildJS"; |   23 v8::Local<v8::Value> RawAccessor(v8::Isolate* isolate) { | 
 |   24   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 
 |   25   i::Zone zone; | 
 |   26   i::compiler::RawMachineAssembler raw_machine_assembler( | 
 |   27       i_isolate, new (&zone) i::compiler::Graph(&zone), | 
 |   28       i::compiler::Linkage::GetJSCallDescriptor( | 
 |   29           &zone, false, 1, i::compiler::CallDescriptor::kNoFlags)); | 
 |   30   raw_machine_assembler.Return(raw_machine_assembler.NumberConstant(41)); | 
 |   31   i::CompilationInfo info("firstChildRaw", i_isolate, &zone); | 
 |   32   i::compiler::Schedule* schedule = raw_machine_assembler.Export(); | 
 |   33   i::Handle<i::Code> code = i::compiler::Pipeline::GenerateCodeForTesting( | 
 |   34       &info, raw_machine_assembler.call_descriptor(), | 
 |   35       raw_machine_assembler.graph(), schedule); | 
 |   36   return v8::Utils::ToLocal(i::Handle<i::Object>::cast(code)); | 
 |   37 } | 
 |   38  | 
|   20  |   39  | 
|   21 TEST(JavascriptAccessors) { |   40 TEST(JavascriptAccessors) { | 
|   22   v8::Isolate* isolate = CcTest::isolate(); |   41   v8::Isolate* isolate = CcTest::isolate(); | 
|   23   v8::HandleScope scope(isolate); |   42   v8::HandleScope scope(isolate); | 
|   24   LocalContext env; |   43   LocalContext env; | 
|   25  |   44  | 
|   26   // We emulate Embedder-created DOM Node instances. Specifically: |   45   // We emulate Embedder-created DOM Node instances. Specifically: | 
|   27   // - 'parent': FunctionTemplate ~= DOM Node superclass |   46   // - 'parent': FunctionTemplate ~= DOM Node superclass | 
|   28   // - 'child':  FunctionTemplate ~= a specific DOM node type, like a <div /> |   47   // - 'child':  FunctionTemplate ~= a specific DOM node type, like a <div /> | 
|   29   // |   48   // | 
|   30   // We'll install both a C++-based and a JS-based accessor on the parent, |   49   // We'll install both a C++-based and a JS-based accessor on the parent, | 
|   31   // and expect it to be callable on the child. |   50   // and expect it to be callable on the child. | 
|   32  |   51  | 
|   33   // Setup the parent template ( =~ DOM Node w/ accessors). |   52   // Setup the parent template ( =~ DOM Node w/ accessors). | 
|   34   v8::Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate); |   53   v8::Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate); | 
|   35   { |   54   { | 
|   36     auto signature = v8::Signature::New(isolate, parent); |   55     auto signature = v8::Signature::New(isolate, parent); | 
|   37  |   56  | 
|   38     // cpp accessor as "firstChild": |   57     // cpp accessor as "firstChild": | 
|   39     parent->PrototypeTemplate()->SetAccessorProperty( |   58     parent->PrototypeTemplate()->SetAccessorProperty( | 
|   40         v8_str("firstChild"), |   59         v8_str("firstChild"), | 
|   41         v8::FunctionTemplate::New(isolate, CppAccessor, v8::Local<v8::Value>(), |   60         v8::FunctionTemplate::New(isolate, CppAccessor, v8::Local<v8::Value>(), | 
|   42                                   signature)); |   61                                   signature)); | 
|   43  |   62  | 
|   44     // JS accessor as "firstChildJS": |   63     // JS accessor as "firstChildRaw": | 
|   45     auto js_accessor = v8::Local<v8::Function>::Cast(CompileRun(JsAccessor)); |   64     auto raw_accessor = RawAccessor(isolate); | 
|   46     parent->PrototypeTemplate()->SetAccessorProperty(v8_str("firstChildJS"), |   65     parent->PrototypeTemplate()->SetAccessorProperty( | 
|   47                                                      js_accessor); |   66         v8_str("firstChildRaw"), | 
 |   67         v8::FunctionTemplate::New(isolate, raw_accessor, v8::Local<v8::Value>(), | 
 |   68                                   signature)); | 
|   48   } |   69   } | 
|   49  |   70  | 
|   50   // Setup child object ( =~ a specific DOM Node, e.g. a <div> ). |   71   // Setup child object ( =~ a specific DOM Node, e.g. a <div> ). | 
|   51   // Also, make a creation function on the global object, so we can access it |   72   // Also, make a creation function on the global object, so we can access it | 
|   52   // in a test. |   73   // in a test. | 
|   53   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate); |   74   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate); | 
|   54   child->Inherit(parent); |   75   child->Inherit(parent); | 
|   55   CHECK(env->Global() |   76   CHECK(env->Global() | 
|   56             ->Set(env.local(), v8_str("Node"), |   77             ->Set(env.local(), v8_str("Node"), | 
|   57                   child->GetFunction(env.local()).ToLocalChecked()) |   78                   child->GetFunction(env.local()).ToLocalChecked()) | 
|   58             .IsJust()); |   79             .IsJust()); | 
|   59  |   80  | 
|   60   // Setup done: Let's test it: |   81   // Setup done: Let's test it: | 
|   61  |   82  | 
|   62   // The simple case: Run it once. |   83   // The simple case: Run it once. | 
|   63   ExpectInt32("var n = new Node(); n.firstChild", 42); |   84   ExpectInt32("var n = new Node(); n.firstChild", 42); | 
|   64   ExpectInt32("var n = new Node(); n.firstChildJS", 41); |   85   ExpectInt32("var n = new Node(); n.firstChildRaw", 41); | 
|   65  |   86  | 
|   66   // Run them in a loop. This will likely trigger the optimizing compiler: |   87   // Run them in a loop. This will likely trigger the optimizing compiler: | 
|   67   ExpectInt32( |   88   ExpectInt32( | 
|   68       "var m = new Node(); " |   89       "var m = new Node(); " | 
|   69       "var sum = 0; " |   90       "var sum = 0; " | 
|   70       "for (var i = 0; i < 3; ++i) { " |   91       "for (var i = 0; i < 3; ++i) { " | 
|   71       "  sum += m.firstChild; " |   92       "  sum += m.firstChild; " | 
|   72       "  sum += m.firstChildJS; " |   93       "  sum += m.firstChildRaw; " | 
|   73       "}; " |   94       "}; " | 
|   74       "sum;", |   95       "sum;", | 
|   75       3 * (42 + 41)); |   96       3 * (42 + 41)); | 
|   76  |   97  | 
|   77   // Obtain the accessor and call it via apply on the Node: |   98   // Obtain the accessor and call it via apply on the Node: | 
|   78   ExpectInt32( |   99   ExpectInt32( | 
|   79       "var n = new Node(); " |  100       "var n = new Node(); " | 
|   80       "var g = Object.getOwnPropertyDescriptor(" |  101       "var g = Object.getOwnPropertyDescriptor(" | 
|   81       "    n.__proto__.__proto__, 'firstChild')['get']; " |  102       "    n.__proto__.__proto__, 'firstChild')['get']; " | 
|   82       "g.apply(n);", |  103       "g.apply(n);", | 
|   83       42); |  104       42); | 
|   84   ExpectInt32( |  105   ExpectInt32( | 
|   85       "var n = new Node(); " |  106       "var n = new Node(); " | 
|   86       "var g = Object.getOwnPropertyDescriptor(" |  107       "var g = Object.getOwnPropertyDescriptor(" | 
|   87       "    n.__proto__.__proto__, 'firstChildJS')['get']; " |  108       "    n.__proto__.__proto__, 'firstChildRaw')['get']; " | 
|   88       "g.apply(n);", |  109       "g.apply(n);", | 
|   89       41); |  110       41); | 
|   90  |  111  | 
|   91   // TODO(vogelheim): Verify compatible receiver check works. |  112   ExpectInt32( | 
 |  113       "var n = new Node();" | 
 |  114       "var g = Object.getOwnPropertyDescriptor(" | 
 |  115       "    n.__proto__.__proto__, 'firstChildRaw')['get'];" | 
 |  116       "try {" | 
 |  117       "  var f = { firstChildRaw: '51' };" | 
 |  118       "  g.apply(f);" | 
 |  119       "} catch(e) {" | 
 |  120       "  31415;" | 
 |  121       "}", | 
 |  122       31415); | 
|   92 } |  123 } | 
|   93 #endif  // V8_JS_ACCESSORS |  124 #endif  // V8_FAST_ACCESSORS | 
| OLD | NEW |