• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 "src/accessors.h"
6 
7 #include "src/api.h"
8 #include "src/contexts.h"
9 #include "src/deoptimizer.h"
10 #include "src/execution.h"
11 #include "src/factory.h"
12 #include "src/frames-inl.h"
13 #include "src/isolate-inl.h"
14 #include "src/list-inl.h"
15 #include "src/messages.h"
16 #include "src/property-details.h"
17 #include "src/prototype.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 
MakeAccessor(Isolate * isolate,Handle<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,PropertyAttributes attributes)23 Handle<AccessorInfo> Accessors::MakeAccessor(
24     Isolate* isolate,
25     Handle<Name> name,
26     AccessorNameGetterCallback getter,
27     AccessorNameSetterCallback setter,
28     PropertyAttributes attributes) {
29   Factory* factory = isolate->factory();
30   Handle<AccessorInfo> info = factory->NewAccessorInfo();
31   info->set_property_attributes(attributes);
32   info->set_all_can_read(false);
33   info->set_all_can_write(false);
34   info->set_is_special_data_property(true);
35   info->set_is_sloppy(false);
36   name = factory->InternalizeName(name);
37   info->set_name(*name);
38   Handle<Object> get = v8::FromCData(isolate, getter);
39   if (setter == nullptr) setter = &ReconfigureToDataProperty;
40   Handle<Object> set = v8::FromCData(isolate, setter);
41   info->set_getter(*get);
42   info->set_setter(*set);
43   Address redirected = info->redirected_getter();
44   if (redirected != nullptr) {
45     Handle<Object> js_get = v8::FromCData(isolate, redirected);
46     info->set_js_getter(*js_get);
47   }
48   return info;
49 }
50 
51 
CheckForName(Handle<Name> name,Handle<String> property_name,int offset,int * object_offset)52 static V8_INLINE bool CheckForName(Handle<Name> name,
53                                    Handle<String> property_name,
54                                    int offset,
55                                    int* object_offset) {
56   if (Name::Equals(name, property_name)) {
57     *object_offset = offset;
58     return true;
59   }
60   return false;
61 }
62 
63 
64 // Returns true for properties that are accessors to object fields.
65 // If true, *object_offset contains offset of object field.
IsJSObjectFieldAccessor(Handle<Map> map,Handle<Name> name,int * object_offset)66 bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
67                                         int* object_offset) {
68   Isolate* isolate = name->GetIsolate();
69 
70   switch (map->instance_type()) {
71     case JS_ARRAY_TYPE:
72       return
73         CheckForName(name, isolate->factory()->length_string(),
74                      JSArray::kLengthOffset, object_offset);
75     case JS_ARRAY_BUFFER_TYPE:
76       return CheckForName(name, isolate->factory()->byte_length_string(),
77                           JSArrayBuffer::kByteLengthOffset, object_offset);
78     default:
79       if (map->instance_type() < FIRST_NONSTRING_TYPE) {
80         return CheckForName(name, isolate->factory()->length_string(),
81                             String::kLengthOffset, object_offset);
82       }
83 
84       return false;
85   }
86 }
87 
88 
89 namespace {
90 
ReplaceAccessorWithDataProperty(Isolate * isolate,Handle<Object> receiver,Handle<JSObject> holder,Handle<Name> name,Handle<Object> value)91 MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty(
92     Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
93     Handle<Name> name, Handle<Object> value) {
94   LookupIterator it(receiver, name, holder,
95                     LookupIterator::OWN_SKIP_INTERCEPTOR);
96   // Skip any access checks we might hit. This accessor should never hit in a
97   // situation where the caller does not have access.
98   if (it.state() == LookupIterator::ACCESS_CHECK) {
99     CHECK(it.HasAccess());
100     it.Next();
101   }
102   DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
103   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
104   it.ReconfigureDataProperty(value, it.property_attributes());
105   return value;
106 }
107 
108 }  // namespace
109 
ReconfigureToDataProperty(v8::Local<v8::Name> key,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)110 void Accessors::ReconfigureToDataProperty(
111     v8::Local<v8::Name> key, v8::Local<v8::Value> val,
112     const v8::PropertyCallbackInfo<void>& info) {
113   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
114   HandleScope scope(isolate);
115   Handle<Object> receiver = Utils::OpenHandle(*info.This());
116   Handle<JSObject> holder =
117       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
118   Handle<Name> name = Utils::OpenHandle(*key);
119   Handle<Object> value = Utils::OpenHandle(*val);
120   MaybeHandle<Object> result =
121       ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
122   if (result.is_null()) isolate->OptionalRescheduleException(false);
123 }
124 
125 //
126 // Accessors::ArgumentsIterator
127 //
128 
129 
ArgumentsIteratorGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)130 void Accessors::ArgumentsIteratorGetter(
131     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
132   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
133   DisallowHeapAllocation no_allocation;
134   HandleScope scope(isolate);
135   Object* result = isolate->native_context()->array_values_iterator();
136   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
137 }
138 
139 
ArgumentsIteratorInfo(Isolate * isolate,PropertyAttributes attributes)140 Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
141     Isolate* isolate, PropertyAttributes attributes) {
142   Handle<Name> name = isolate->factory()->iterator_symbol();
143   return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr,
144                       attributes);
145 }
146 
147 
148 //
149 // Accessors::ArrayLength
150 //
151 
152 
ArrayLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)153 void Accessors::ArrayLengthGetter(
154     v8::Local<v8::Name> name,
155     const v8::PropertyCallbackInfo<v8::Value>& info) {
156   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
157   DisallowHeapAllocation no_allocation;
158   HandleScope scope(isolate);
159   JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
160   Object* result = holder->length();
161   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
162 }
163 
164 
ArrayLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)165 void Accessors::ArrayLengthSetter(
166     v8::Local<v8::Name> name,
167     v8::Local<v8::Value> val,
168     const v8::PropertyCallbackInfo<void>& info) {
169   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
170   HandleScope scope(isolate);
171 
172   Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
173   Handle<JSArray> array = Handle<JSArray>::cast(object);
174   Handle<Object> length_obj = Utils::OpenHandle(*val);
175 
176   uint32_t length = 0;
177   if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
178     isolate->OptionalRescheduleException(false);
179     return;
180   }
181 
182   JSArray::SetLength(array, length);
183 
184   if (info.ShouldThrowOnError()) {
185     uint32_t actual_new_len = 0;
186     CHECK(array->length()->ToArrayLength(&actual_new_len));
187     // Throw TypeError if there were non-deletable elements.
188     if (actual_new_len != length) {
189       Factory* factory = isolate->factory();
190       isolate->Throw(*factory->NewTypeError(
191           MessageTemplate::kStrictDeleteProperty,
192           factory->NewNumberFromUint(actual_new_len - 1), array));
193       isolate->OptionalRescheduleException(false);
194     }
195   }
196 }
197 
198 
ArrayLengthInfo(Isolate * isolate,PropertyAttributes attributes)199 Handle<AccessorInfo> Accessors::ArrayLengthInfo(
200       Isolate* isolate, PropertyAttributes attributes) {
201   return MakeAccessor(isolate,
202                       isolate->factory()->length_string(),
203                       &ArrayLengthGetter,
204                       &ArrayLengthSetter,
205                       attributes);
206 }
207 
208 
209 //
210 // Accessors::StringLength
211 //
212 
StringLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)213 void Accessors::StringLengthGetter(
214     v8::Local<v8::Name> name,
215     const v8::PropertyCallbackInfo<v8::Value>& info) {
216   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
217   DisallowHeapAllocation no_allocation;
218   HandleScope scope(isolate);
219 
220   // We have a slight impedance mismatch between the external API and the way we
221   // use callbacks internally: Externally, callbacks can only be used with
222   // v8::Object, but internally we have callbacks on entities which are higher
223   // in the hierarchy, in this case for String values.
224 
225   Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
226   if (!value->IsString()) {
227     // Not a string value. That means that we either got a String wrapper or
228     // a Value with a String wrapper in its prototype chain.
229     value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
230   }
231   Object* result = Smi::FromInt(String::cast(value)->length());
232   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
233 }
234 
235 
StringLengthInfo(Isolate * isolate,PropertyAttributes attributes)236 Handle<AccessorInfo> Accessors::StringLengthInfo(
237       Isolate* isolate, PropertyAttributes attributes) {
238   return MakeAccessor(isolate, isolate->factory()->length_string(),
239                       &StringLengthGetter, nullptr, attributes);
240 }
241 
242 
243 //
244 // Accessors::ScriptColumnOffset
245 //
246 
247 
ScriptColumnOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)248 void Accessors::ScriptColumnOffsetGetter(
249     v8::Local<v8::Name> name,
250     const v8::PropertyCallbackInfo<v8::Value>& info) {
251   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
252   DisallowHeapAllocation no_allocation;
253   HandleScope scope(isolate);
254   Object* object = *Utils::OpenHandle(*info.Holder());
255   Object* res = Smi::FromInt(
256       Script::cast(JSValue::cast(object)->value())->column_offset());
257   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
258 }
259 
260 
ScriptColumnOffsetInfo(Isolate * isolate,PropertyAttributes attributes)261 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
262       Isolate* isolate, PropertyAttributes attributes) {
263   Handle<String> name(isolate->factory()->InternalizeOneByteString(
264       STATIC_CHAR_VECTOR("column_offset")));
265   return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr,
266                       attributes);
267 }
268 
269 
270 //
271 // Accessors::ScriptId
272 //
273 
274 
ScriptIdGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)275 void Accessors::ScriptIdGetter(
276     v8::Local<v8::Name> name,
277     const v8::PropertyCallbackInfo<v8::Value>& info) {
278   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
279   DisallowHeapAllocation no_allocation;
280   HandleScope scope(isolate);
281   Object* object = *Utils::OpenHandle(*info.Holder());
282   Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id());
283   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
284 }
285 
286 
ScriptIdInfo(Isolate * isolate,PropertyAttributes attributes)287 Handle<AccessorInfo> Accessors::ScriptIdInfo(
288       Isolate* isolate, PropertyAttributes attributes) {
289   Handle<String> name(
290       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
291   return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes);
292 }
293 
294 
295 //
296 // Accessors::ScriptName
297 //
298 
299 
ScriptNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)300 void Accessors::ScriptNameGetter(
301     v8::Local<v8::Name> name,
302     const v8::PropertyCallbackInfo<v8::Value>& info) {
303   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
304   DisallowHeapAllocation no_allocation;
305   HandleScope scope(isolate);
306   Object* object = *Utils::OpenHandle(*info.Holder());
307   Object* source = Script::cast(JSValue::cast(object)->value())->name();
308   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
309 }
310 
311 
ScriptNameInfo(Isolate * isolate,PropertyAttributes attributes)312 Handle<AccessorInfo> Accessors::ScriptNameInfo(
313       Isolate* isolate, PropertyAttributes attributes) {
314   return MakeAccessor(isolate, isolate->factory()->name_string(),
315                       &ScriptNameGetter, nullptr, attributes);
316 }
317 
318 
319 //
320 // Accessors::ScriptSource
321 //
322 
323 
ScriptSourceGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)324 void Accessors::ScriptSourceGetter(
325     v8::Local<v8::Name> name,
326     const v8::PropertyCallbackInfo<v8::Value>& info) {
327   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
328   DisallowHeapAllocation no_allocation;
329   HandleScope scope(isolate);
330   Object* object = *Utils::OpenHandle(*info.Holder());
331   Object* source = Script::cast(JSValue::cast(object)->value())->source();
332   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
333 }
334 
335 
ScriptSourceInfo(Isolate * isolate,PropertyAttributes attributes)336 Handle<AccessorInfo> Accessors::ScriptSourceInfo(
337       Isolate* isolate, PropertyAttributes attributes) {
338   return MakeAccessor(isolate, isolate->factory()->source_string(),
339                       &ScriptSourceGetter, nullptr, attributes);
340 }
341 
342 
343 //
344 // Accessors::ScriptLineOffset
345 //
346 
347 
ScriptLineOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)348 void Accessors::ScriptLineOffsetGetter(
349     v8::Local<v8::Name> name,
350     const v8::PropertyCallbackInfo<v8::Value>& info) {
351   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
352   DisallowHeapAllocation no_allocation;
353   HandleScope scope(isolate);
354   Object* object = *Utils::OpenHandle(*info.Holder());
355   Object* res =
356       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset());
357   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
358 }
359 
360 
ScriptLineOffsetInfo(Isolate * isolate,PropertyAttributes attributes)361 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
362       Isolate* isolate, PropertyAttributes attributes) {
363   Handle<String> name(isolate->factory()->InternalizeOneByteString(
364       STATIC_CHAR_VECTOR("line_offset")));
365   return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr,
366                       attributes);
367 }
368 
369 
370 //
371 // Accessors::ScriptType
372 //
373 
374 
ScriptTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)375 void Accessors::ScriptTypeGetter(
376     v8::Local<v8::Name> name,
377     const v8::PropertyCallbackInfo<v8::Value>& info) {
378   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
379   DisallowHeapAllocation no_allocation;
380   HandleScope scope(isolate);
381   Object* object = *Utils::OpenHandle(*info.Holder());
382   Object* res =
383       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type());
384   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
385 }
386 
387 
ScriptTypeInfo(Isolate * isolate,PropertyAttributes attributes)388 Handle<AccessorInfo> Accessors::ScriptTypeInfo(
389       Isolate* isolate, PropertyAttributes attributes) {
390   Handle<String> name(
391       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
392   return MakeAccessor(isolate, name, &ScriptTypeGetter, nullptr, attributes);
393 }
394 
395 
396 //
397 // Accessors::ScriptCompilationType
398 //
399 
400 
ScriptCompilationTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)401 void Accessors::ScriptCompilationTypeGetter(
402     v8::Local<v8::Name> name,
403     const v8::PropertyCallbackInfo<v8::Value>& info) {
404   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
405   DisallowHeapAllocation no_allocation;
406   HandleScope scope(isolate);
407   Object* object = *Utils::OpenHandle(*info.Holder());
408   Object* res = Smi::FromInt(
409       Script::cast(JSValue::cast(object)->value())->compilation_type());
410   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
411 }
412 
413 
ScriptCompilationTypeInfo(Isolate * isolate,PropertyAttributes attributes)414 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
415       Isolate* isolate, PropertyAttributes attributes) {
416   Handle<String> name(isolate->factory()->InternalizeOneByteString(
417       STATIC_CHAR_VECTOR("compilation_type")));
418   return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr,
419                       attributes);
420 }
421 
422 
423 //
424 // Accessors::ScriptGetLineEnds
425 //
426 
427 
ScriptLineEndsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)428 void Accessors::ScriptLineEndsGetter(
429     v8::Local<v8::Name> name,
430     const v8::PropertyCallbackInfo<v8::Value>& info) {
431   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
432   HandleScope scope(isolate);
433   Handle<Object> object = Utils::OpenHandle(*info.Holder());
434   Handle<Script> script(
435       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
436   Script::InitLineEnds(script);
437   DCHECK(script->line_ends()->IsFixedArray());
438   Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
439   // We do not want anyone to modify this array from JS.
440   DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
441          line_ends->map() == isolate->heap()->fixed_cow_array_map());
442   Handle<JSArray> js_array =
443       isolate->factory()->NewJSArrayWithElements(line_ends);
444   info.GetReturnValue().Set(Utils::ToLocal(js_array));
445 }
446 
447 
ScriptLineEndsInfo(Isolate * isolate,PropertyAttributes attributes)448 Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
449       Isolate* isolate, PropertyAttributes attributes) {
450   Handle<String> name(isolate->factory()->InternalizeOneByteString(
451       STATIC_CHAR_VECTOR("line_ends")));
452   return MakeAccessor(isolate, name, &ScriptLineEndsGetter, nullptr,
453                       attributes);
454 }
455 
456 
457 //
458 // Accessors::ScriptSourceUrl
459 //
460 
461 
ScriptSourceUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)462 void Accessors::ScriptSourceUrlGetter(
463     v8::Local<v8::Name> name,
464     const v8::PropertyCallbackInfo<v8::Value>& info) {
465   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
466   DisallowHeapAllocation no_allocation;
467   HandleScope scope(isolate);
468   Object* object = *Utils::OpenHandle(*info.Holder());
469   Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
470   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
471 }
472 
473 
ScriptSourceUrlInfo(Isolate * isolate,PropertyAttributes attributes)474 Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
475       Isolate* isolate, PropertyAttributes attributes) {
476   return MakeAccessor(isolate, isolate->factory()->source_url_string(),
477                       &ScriptSourceUrlGetter, nullptr, attributes);
478 }
479 
480 
481 //
482 // Accessors::ScriptSourceMappingUrl
483 //
484 
485 
ScriptSourceMappingUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)486 void Accessors::ScriptSourceMappingUrlGetter(
487     v8::Local<v8::Name> name,
488     const v8::PropertyCallbackInfo<v8::Value>& info) {
489   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
490   DisallowHeapAllocation no_allocation;
491   HandleScope scope(isolate);
492   Object* object = *Utils::OpenHandle(*info.Holder());
493   Object* url =
494       Script::cast(JSValue::cast(object)->value())->source_mapping_url();
495   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
496 }
497 
498 
ScriptSourceMappingUrlInfo(Isolate * isolate,PropertyAttributes attributes)499 Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
500       Isolate* isolate, PropertyAttributes attributes) {
501   return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(),
502                       &ScriptSourceMappingUrlGetter, nullptr, attributes);
503 }
504 
505 
506 //
507 // Accessors::ScriptIsEmbedderDebugScript
508 //
509 
510 
ScriptIsEmbedderDebugScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)511 void Accessors::ScriptIsEmbedderDebugScriptGetter(
512     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
513   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
514   DisallowHeapAllocation no_allocation;
515   HandleScope scope(isolate);
516   Object* object = *Utils::OpenHandle(*info.Holder());
517   bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
518                                       ->origin_options()
519                                       .IsEmbedderDebugScript();
520   Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script);
521   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
522 }
523 
524 
ScriptIsEmbedderDebugScriptInfo(Isolate * isolate,PropertyAttributes attributes)525 Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo(
526     Isolate* isolate, PropertyAttributes attributes) {
527   Handle<String> name(isolate->factory()->InternalizeOneByteString(
528       STATIC_CHAR_VECTOR("is_debugger_script")));
529   return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter,
530                       nullptr, attributes);
531 }
532 
533 
534 //
535 // Accessors::ScriptGetContextData
536 //
537 
538 
ScriptContextDataGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)539 void Accessors::ScriptContextDataGetter(
540     v8::Local<v8::Name> name,
541     const v8::PropertyCallbackInfo<v8::Value>& info) {
542   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
543   DisallowHeapAllocation no_allocation;
544   HandleScope scope(isolate);
545   Object* object = *Utils::OpenHandle(*info.Holder());
546   Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
547   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
548 }
549 
550 
ScriptContextDataInfo(Isolate * isolate,PropertyAttributes attributes)551 Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
552       Isolate* isolate, PropertyAttributes attributes) {
553   Handle<String> name(isolate->factory()->InternalizeOneByteString(
554       STATIC_CHAR_VECTOR("context_data")));
555   return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr,
556                       attributes);
557 }
558 
559 
560 //
561 // Accessors::ScriptGetEvalFromScript
562 //
563 
564 
ScriptEvalFromScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)565 void Accessors::ScriptEvalFromScriptGetter(
566     v8::Local<v8::Name> name,
567     const v8::PropertyCallbackInfo<v8::Value>& info) {
568   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
569   HandleScope scope(isolate);
570   Handle<Object> object = Utils::OpenHandle(*info.Holder());
571   Handle<Script> script(
572       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
573   Handle<Object> result = isolate->factory()->undefined_value();
574   if (!script->eval_from_shared()->IsUndefined(isolate)) {
575     Handle<SharedFunctionInfo> eval_from_shared(
576         SharedFunctionInfo::cast(script->eval_from_shared()));
577     if (eval_from_shared->script()->IsScript()) {
578       Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
579       result = Script::GetWrapper(eval_from_script);
580     }
581   }
582 
583   info.GetReturnValue().Set(Utils::ToLocal(result));
584 }
585 
586 
ScriptEvalFromScriptInfo(Isolate * isolate,PropertyAttributes attributes)587 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
588       Isolate* isolate, PropertyAttributes attributes) {
589   Handle<String> name(isolate->factory()->InternalizeOneByteString(
590       STATIC_CHAR_VECTOR("eval_from_script")));
591   return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr,
592                       attributes);
593 }
594 
595 
596 //
597 // Accessors::ScriptGetEvalFromScriptPosition
598 //
599 
600 
ScriptEvalFromScriptPositionGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)601 void Accessors::ScriptEvalFromScriptPositionGetter(
602     v8::Local<v8::Name> name,
603     const v8::PropertyCallbackInfo<v8::Value>& info) {
604   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
605   HandleScope scope(isolate);
606   Handle<Object> object = Utils::OpenHandle(*info.Holder());
607   Handle<Script> script(
608       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
609   Handle<Object> result = isolate->factory()->undefined_value();
610   if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
611     result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate);
612   }
613   info.GetReturnValue().Set(Utils::ToLocal(result));
614 }
615 
616 
ScriptEvalFromScriptPositionInfo(Isolate * isolate,PropertyAttributes attributes)617 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
618       Isolate* isolate, PropertyAttributes attributes) {
619   Handle<String> name(isolate->factory()->InternalizeOneByteString(
620       STATIC_CHAR_VECTOR("eval_from_script_position")));
621   return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter,
622                       nullptr, attributes);
623 }
624 
625 
626 //
627 // Accessors::ScriptGetEvalFromFunctionName
628 //
629 
630 
ScriptEvalFromFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)631 void Accessors::ScriptEvalFromFunctionNameGetter(
632     v8::Local<v8::Name> name,
633     const v8::PropertyCallbackInfo<v8::Value>& info) {
634   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
635   HandleScope scope(isolate);
636   Handle<Object> object = Utils::OpenHandle(*info.Holder());
637   Handle<Script> script(
638       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
639   Handle<Object> result = isolate->factory()->undefined_value();
640   if (!script->eval_from_shared()->IsUndefined(isolate)) {
641     Handle<SharedFunctionInfo> shared(
642         SharedFunctionInfo::cast(script->eval_from_shared()));
643     // Find the name of the function calling eval.
644     if (!shared->name()->IsUndefined(isolate)) {
645       result = Handle<Object>(shared->name(), isolate);
646     } else {
647       result = Handle<Object>(shared->inferred_name(), isolate);
648     }
649   }
650   info.GetReturnValue().Set(Utils::ToLocal(result));
651 }
652 
653 
ScriptEvalFromFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)654 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
655       Isolate* isolate, PropertyAttributes attributes) {
656   Handle<String> name(isolate->factory()->InternalizeOneByteString(
657       STATIC_CHAR_VECTOR("eval_from_function_name")));
658   return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr,
659                       attributes);
660 }
661 
662 
663 //
664 // Accessors::FunctionPrototype
665 //
666 
GetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function)667 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
668                                            Handle<JSFunction> function) {
669   if (!function->has_prototype()) {
670     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
671     JSFunction::SetPrototype(function, proto);
672   }
673   return Handle<Object>(function->prototype(), isolate);
674 }
675 
676 
SetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function,Handle<Object> value)677 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
678     Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
679   JSFunction::SetPrototype(function, value);
680   DCHECK(function->prototype() == *value);
681   return function;
682 }
683 
684 
FunctionSetPrototype(Handle<JSFunction> function,Handle<Object> prototype)685 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
686                                                     Handle<Object> prototype) {
687   DCHECK(function->IsConstructor());
688   Isolate* isolate = function->GetIsolate();
689   return SetFunctionPrototype(isolate, function, prototype);
690 }
691 
692 
FunctionPrototypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)693 void Accessors::FunctionPrototypeGetter(
694     v8::Local<v8::Name> name,
695     const v8::PropertyCallbackInfo<v8::Value>& info) {
696   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
697   HandleScope scope(isolate);
698   Handle<JSFunction> function =
699       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
700   Handle<Object> result = GetFunctionPrototype(isolate, function);
701   info.GetReturnValue().Set(Utils::ToLocal(result));
702 }
703 
704 
FunctionPrototypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)705 void Accessors::FunctionPrototypeSetter(
706     v8::Local<v8::Name> name,
707     v8::Local<v8::Value> val,
708     const v8::PropertyCallbackInfo<void>& info) {
709   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
710   HandleScope scope(isolate);
711   Handle<Object> value = Utils::OpenHandle(*val);
712   Handle<JSFunction> object =
713       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
714   if (SetFunctionPrototype(isolate, object, value).is_null()) {
715     isolate->OptionalRescheduleException(false);
716   }
717 }
718 
719 
FunctionPrototypeInfo(Isolate * isolate,PropertyAttributes attributes)720 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
721       Isolate* isolate, PropertyAttributes attributes) {
722   return MakeAccessor(isolate,
723                       isolate->factory()->prototype_string(),
724                       &FunctionPrototypeGetter,
725                       &FunctionPrototypeSetter,
726                       attributes);
727 }
728 
729 
730 //
731 // Accessors::FunctionLength
732 //
733 
734 
FunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)735 void Accessors::FunctionLengthGetter(
736     v8::Local<v8::Name> name,
737     const v8::PropertyCallbackInfo<v8::Value>& info) {
738   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
739   HandleScope scope(isolate);
740   Handle<JSFunction> function =
741       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
742   Handle<Object> result;
743   if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) {
744     result = handle(Smi::FromInt(0), isolate);
745     isolate->OptionalRescheduleException(false);
746   }
747 
748   info.GetReturnValue().Set(Utils::ToLocal(result));
749 }
750 
FunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)751 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
752       Isolate* isolate, PropertyAttributes attributes) {
753   return MakeAccessor(isolate, isolate->factory()->length_string(),
754                       &FunctionLengthGetter, &ReconfigureToDataProperty,
755                       attributes);
756 }
757 
758 
759 //
760 // Accessors::FunctionName
761 //
762 
763 
FunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)764 void Accessors::FunctionNameGetter(
765     v8::Local<v8::Name> name,
766     const v8::PropertyCallbackInfo<v8::Value>& info) {
767   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
768   HandleScope scope(isolate);
769   Handle<JSFunction> function =
770       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
771   Handle<Object> result = JSFunction::GetName(isolate, function);
772   info.GetReturnValue().Set(Utils::ToLocal(result));
773 }
774 
FunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)775 Handle<AccessorInfo> Accessors::FunctionNameInfo(
776       Isolate* isolate, PropertyAttributes attributes) {
777   return MakeAccessor(isolate, isolate->factory()->name_string(),
778                       &FunctionNameGetter, &ReconfigureToDataProperty,
779                       attributes);
780 }
781 
782 
783 //
784 // Accessors::FunctionArguments
785 //
786 
787 
ArgumentsForInlinedFunction(JavaScriptFrame * frame,Handle<JSFunction> inlined_function,int inlined_frame_index)788 static Handle<Object> ArgumentsForInlinedFunction(
789     JavaScriptFrame* frame,
790     Handle<JSFunction> inlined_function,
791     int inlined_frame_index) {
792   Isolate* isolate = inlined_function->GetIsolate();
793   Factory* factory = isolate->factory();
794 
795   TranslatedState translated_values(frame);
796   translated_values.Prepare(false, frame->fp());
797 
798   int argument_count = 0;
799   TranslatedFrame* translated_frame =
800       translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
801                                                          &argument_count);
802   TranslatedFrame::iterator iter = translated_frame->begin();
803 
804   // Skip the function.
805   iter++;
806 
807   // Skip the receiver.
808   iter++;
809   argument_count--;
810 
811   Handle<JSObject> arguments =
812       factory->NewArgumentsObject(inlined_function, argument_count);
813   Handle<FixedArray> array = factory->NewFixedArray(argument_count);
814   bool should_deoptimize = false;
815   for (int i = 0; i < argument_count; ++i) {
816     // If we materialize any object, we should deopt because we might alias
817     // an object that was eliminated by escape analysis.
818     should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
819     Handle<Object> value = iter->GetValue();
820     array->set(i, *value);
821     iter++;
822   }
823   arguments->set_elements(*array);
824 
825   if (should_deoptimize) {
826     translated_values.StoreMaterializedValuesAndDeopt();
827   }
828 
829   // Return the freshly allocated arguments object.
830   return arguments;
831 }
832 
833 
FindFunctionInFrame(JavaScriptFrame * frame,Handle<JSFunction> function)834 static int FindFunctionInFrame(JavaScriptFrame* frame,
835                                Handle<JSFunction> function) {
836   DisallowHeapAllocation no_allocation;
837   List<JSFunction*> functions(2);
838   frame->GetFunctions(&functions);
839   for (int i = functions.length() - 1; i >= 0; i--) {
840     if (functions[i] == *function) return i;
841   }
842   return -1;
843 }
844 
845 
846 namespace {
847 
GetFunctionArguments(Isolate * isolate,Handle<JSFunction> function)848 Handle<Object> GetFunctionArguments(Isolate* isolate,
849                                     Handle<JSFunction> function) {
850   // Find the top invocation of the function by traversing frames.
851   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
852     JavaScriptFrame* frame = it.frame();
853     int function_index = FindFunctionInFrame(frame, function);
854     if (function_index < 0) continue;
855 
856     if (function_index > 0) {
857       // The function in question was inlined.  Inlined functions have the
858       // correct number of arguments and no allocated arguments object, so
859       // we can construct a fresh one by interpreting the function's
860       // deoptimization input data.
861       return ArgumentsForInlinedFunction(frame, function, function_index);
862     }
863 
864     // Find the frame that holds the actual arguments passed to the function.
865     it.AdvanceToArgumentsFrame();
866     frame = it.frame();
867 
868     // Get the number of arguments and construct an arguments object
869     // mirror for the right frame.
870     const int length = frame->ComputeParametersCount();
871     Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
872         function, length);
873     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
874 
875     // Copy the parameters to the arguments object.
876     DCHECK(array->length() == length);
877     for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
878     arguments->set_elements(*array);
879 
880     // Return the freshly allocated arguments object.
881     return arguments;
882   }
883 
884   // No frame corresponding to the given function found. Return null.
885   return isolate->factory()->null_value();
886 }
887 
888 }  // namespace
889 
890 
FunctionGetArguments(Handle<JSFunction> function)891 Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
892   Handle<Object> arguments =
893       GetFunctionArguments(function->GetIsolate(), function);
894   CHECK(arguments->IsJSObject());
895   return Handle<JSObject>::cast(arguments);
896 }
897 
898 
FunctionArgumentsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)899 void Accessors::FunctionArgumentsGetter(
900     v8::Local<v8::Name> name,
901     const v8::PropertyCallbackInfo<v8::Value>& info) {
902   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
903   HandleScope scope(isolate);
904   Handle<JSFunction> function =
905       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
906   Handle<Object> result =
907       function->shared()->native()
908           ? Handle<Object>::cast(isolate->factory()->null_value())
909           : GetFunctionArguments(isolate, function);
910   info.GetReturnValue().Set(Utils::ToLocal(result));
911 }
912 
913 
FunctionArgumentsInfo(Isolate * isolate,PropertyAttributes attributes)914 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
915       Isolate* isolate, PropertyAttributes attributes) {
916   return MakeAccessor(isolate, isolate->factory()->arguments_string(),
917                       &FunctionArgumentsGetter, nullptr, attributes);
918 }
919 
920 
921 //
922 // Accessors::FunctionCaller
923 //
924 
925 
AllowAccessToFunction(Context * current_context,JSFunction * function)926 static inline bool AllowAccessToFunction(Context* current_context,
927                                          JSFunction* function) {
928   return current_context->HasSameSecurityTokenAs(function->context());
929 }
930 
931 
932 class FrameFunctionIterator {
933  public:
FrameFunctionIterator(Isolate * isolate,const DisallowHeapAllocation & promise)934   FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
935       : isolate_(isolate),
936         frame_iterator_(isolate),
937         functions_(2),
938         index_(0) {
939     GetFunctions();
940   }
next()941   JSFunction* next() {
942     while (true) {
943       if (functions_.length() == 0) return NULL;
944       JSFunction* next_function = functions_[index_];
945       index_--;
946       if (index_ < 0) {
947         GetFunctions();
948       }
949       // Skip functions from other origins.
950       if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
951       return next_function;
952     }
953   }
954 
955   // Iterate through functions until the first occurence of 'function'.
956   // Returns true if 'function' is found, and false if the iterator ends
957   // without finding it.
Find(JSFunction * function)958   bool Find(JSFunction* function) {
959     JSFunction* next_function;
960     do {
961       next_function = next();
962       if (next_function == function) return true;
963     } while (next_function != NULL);
964     return false;
965   }
966 
967  private:
GetFunctions()968   void GetFunctions() {
969     functions_.Rewind(0);
970     if (frame_iterator_.done()) return;
971     JavaScriptFrame* frame = frame_iterator_.frame();
972     frame->GetFunctions(&functions_);
973     DCHECK(functions_.length() > 0);
974     frame_iterator_.Advance();
975     index_ = functions_.length() - 1;
976   }
977   Isolate* isolate_;
978   JavaScriptFrameIterator frame_iterator_;
979   List<JSFunction*> functions_;
980   int index_;
981 };
982 
983 
FindCaller(Isolate * isolate,Handle<JSFunction> function)984 MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
985                                    Handle<JSFunction> function) {
986   DisallowHeapAllocation no_allocation;
987   FrameFunctionIterator it(isolate, no_allocation);
988   if (function->shared()->native()) {
989     return MaybeHandle<JSFunction>();
990   }
991   // Find the function from the frames.
992   if (!it.Find(*function)) {
993     // No frame corresponding to the given function found. Return null.
994     return MaybeHandle<JSFunction>();
995   }
996   // Find previously called non-toplevel function.
997   JSFunction* caller;
998   do {
999     caller = it.next();
1000     if (caller == NULL) return MaybeHandle<JSFunction>();
1001   } while (caller->shared()->is_toplevel());
1002 
1003   // If caller is a built-in function and caller's caller is also built-in,
1004   // use that instead.
1005   JSFunction* potential_caller = caller;
1006   while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) {
1007     caller = potential_caller;
1008     potential_caller = it.next();
1009   }
1010   if (!caller->shared()->native() && potential_caller != NULL) {
1011     caller = potential_caller;
1012   }
1013   // Censor if the caller is not a sloppy mode function.
1014   // Change from ES5, which used to throw, see:
1015   // https://bugs.ecmascript.org/show_bug.cgi?id=310
1016   if (is_strict(caller->shared()->language_mode())) {
1017     return MaybeHandle<JSFunction>();
1018   }
1019   // Don't return caller from another security context.
1020   if (!AllowAccessToFunction(isolate->context(), caller)) {
1021     return MaybeHandle<JSFunction>();
1022   }
1023   return Handle<JSFunction>(caller);
1024 }
1025 
1026 
FunctionCallerGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1027 void Accessors::FunctionCallerGetter(
1028     v8::Local<v8::Name> name,
1029     const v8::PropertyCallbackInfo<v8::Value>& info) {
1030   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1031   HandleScope scope(isolate);
1032   Handle<JSFunction> function =
1033       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1034   Handle<Object> result;
1035   MaybeHandle<JSFunction> maybe_caller;
1036   maybe_caller = FindCaller(isolate, function);
1037   Handle<JSFunction> caller;
1038   if (maybe_caller.ToHandle(&caller)) {
1039     result = caller;
1040   } else {
1041     result = isolate->factory()->null_value();
1042   }
1043   info.GetReturnValue().Set(Utils::ToLocal(result));
1044 }
1045 
1046 
FunctionCallerInfo(Isolate * isolate,PropertyAttributes attributes)1047 Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1048       Isolate* isolate, PropertyAttributes attributes) {
1049   return MakeAccessor(isolate, isolate->factory()->caller_string(),
1050                       &FunctionCallerGetter, nullptr, attributes);
1051 }
1052 
1053 
1054 //
1055 // Accessors::BoundFunctionLength
1056 //
1057 
BoundFunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1058 void Accessors::BoundFunctionLengthGetter(
1059     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1060   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1061   HandleScope scope(isolate);
1062   Handle<JSBoundFunction> function =
1063       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1064 
1065   Handle<Smi> target_length;
1066   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
1067                             isolate);
1068   if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) {
1069     target_length = handle(Smi::FromInt(0), isolate);
1070     isolate->OptionalRescheduleException(false);
1071     return;
1072   }
1073 
1074   int bound_length = function->bound_arguments()->length();
1075   int length = Max(0, target_length->value() - bound_length);
1076 
1077   Handle<Object> result(Smi::FromInt(length), isolate);
1078   info.GetReturnValue().Set(Utils::ToLocal(result));
1079 }
1080 
BoundFunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)1081 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
1082     Isolate* isolate, PropertyAttributes attributes) {
1083   return MakeAccessor(isolate, isolate->factory()->length_string(),
1084                       &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
1085                       attributes);
1086 }
1087 
1088 //
1089 // Accessors::BoundFunctionName
1090 //
1091 
BoundFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1092 void Accessors::BoundFunctionNameGetter(
1093     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1094   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1095   HandleScope scope(isolate);
1096   Handle<JSBoundFunction> function =
1097       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1098   Handle<Object> result;
1099   if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
1100     isolate->OptionalRescheduleException(false);
1101     return;
1102   }
1103   info.GetReturnValue().Set(Utils::ToLocal(result));
1104 }
1105 
BoundFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)1106 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
1107     Isolate* isolate, PropertyAttributes attributes) {
1108   return MakeAccessor(isolate, isolate->factory()->name_string(),
1109                       &BoundFunctionNameGetter, &ReconfigureToDataProperty,
1110                       attributes);
1111 }
1112 
1113 //
1114 // Accessors::MakeModuleExport
1115 //
1116 
ModuleGetExport(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info)1117 static void ModuleGetExport(v8::Local<v8::Name> property,
1118                             const v8::PropertyCallbackInfo<v8::Value>& info) {
1119   JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1120   Context* context = Context::cast(instance->context());
1121   DCHECK(context->IsModuleContext());
1122   Isolate* isolate = instance->GetIsolate();
1123   int slot = info.Data()
1124                  ->Int32Value(info.GetIsolate()->GetCurrentContext())
1125                  .FromMaybe(-1);
1126   if (slot < 0 || slot >= context->length()) {
1127     Handle<Name> name = v8::Utils::OpenHandle(*property);
1128 
1129     Handle<Object> exception = isolate->factory()->NewReferenceError(
1130         MessageTemplate::kNotDefined, name);
1131     isolate->ScheduleThrow(*exception);
1132     return;
1133   }
1134   Object* value = context->get(slot);
1135   if (value->IsTheHole(isolate)) {
1136     Handle<Name> name = v8::Utils::OpenHandle(*property);
1137 
1138     Handle<Object> exception = isolate->factory()->NewReferenceError(
1139         MessageTemplate::kNotDefined, name);
1140     isolate->ScheduleThrow(*exception);
1141     return;
1142   }
1143   info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
1144 }
1145 
1146 
ModuleSetExport(v8::Local<v8::Name> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)1147 static void ModuleSetExport(v8::Local<v8::Name> property,
1148                             v8::Local<v8::Value> value,
1149                             const v8::PropertyCallbackInfo<void>& info) {
1150   if (!info.ShouldThrowOnError()) return;
1151   Handle<Name> name = v8::Utils::OpenHandle(*property);
1152   Isolate* isolate = name->GetIsolate();
1153   Handle<Object> exception =
1154       isolate->factory()->NewTypeError(MessageTemplate::kNotDefined, name);
1155   isolate->ScheduleThrow(*exception);
1156 }
1157 
1158 
MakeModuleExport(Handle<String> name,int index,PropertyAttributes attributes)1159 Handle<AccessorInfo> Accessors::MakeModuleExport(
1160     Handle<String> name,
1161     int index,
1162     PropertyAttributes attributes) {
1163   Isolate* isolate = name->GetIsolate();
1164   Handle<AccessorInfo> info = MakeAccessor(isolate, name, &ModuleGetExport,
1165                                            &ModuleSetExport, attributes);
1166   info->set_data(Smi::FromInt(index));
1167   return info;
1168 }
1169 
1170 
1171 }  // namespace internal
1172 }  // namespace v8
1173