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/v8.h"
6
7#include "src/accessors.h"
8#include "src/api.h"
9#include "src/compiler.h"
10#include "src/contexts.h"
11#include "src/deoptimizer.h"
12#include "src/execution.h"
13#include "src/factory.h"
14#include "src/frames-inl.h"
15#include "src/isolate.h"
16#include "src/list-inl.h"
17#include "src/property-details.h"
18#include "src/prototype.h"
19
20namespace v8 {
21namespace internal {
22
23
24Handle<AccessorInfo> Accessors::MakeAccessor(
25    Isolate* isolate,
26    Handle<Name> name,
27    AccessorNameGetterCallback getter,
28    AccessorNameSetterCallback setter,
29    PropertyAttributes attributes) {
30  Factory* factory = isolate->factory();
31  Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
32  info->set_property_attributes(attributes);
33  info->set_all_can_read(false);
34  info->set_all_can_write(false);
35  info->set_name(*name);
36  Handle<Object> get = v8::FromCData(isolate, getter);
37  Handle<Object> set = v8::FromCData(isolate, setter);
38  info->set_getter(*get);
39  info->set_setter(*set);
40  return info;
41}
42
43
44Handle<ExecutableAccessorInfo> Accessors::CloneAccessor(
45    Isolate* isolate,
46    Handle<ExecutableAccessorInfo> accessor) {
47  Factory* factory = isolate->factory();
48  Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
49  info->set_name(accessor->name());
50  info->set_flag(accessor->flag());
51  info->set_expected_receiver_type(accessor->expected_receiver_type());
52  info->set_getter(accessor->getter());
53  info->set_setter(accessor->setter());
54  info->set_data(accessor->data());
55  return info;
56}
57
58
59template <class C>
60static C* FindInstanceOf(Isolate* isolate, Object* obj) {
61  for (PrototypeIterator iter(isolate, obj,
62                              PrototypeIterator::START_AT_RECEIVER);
63       !iter.IsAtEnd(); iter.Advance()) {
64    if (Is<C>(iter.GetCurrent())) return C::cast(iter.GetCurrent());
65  }
66  return NULL;
67}
68
69
70static V8_INLINE bool CheckForName(Handle<Name> name,
71                                   Handle<String> property_name,
72                                   int offset,
73                                   int* object_offset) {
74  if (Name::Equals(name, property_name)) {
75    *object_offset = offset;
76    return true;
77  }
78  return false;
79}
80
81
82// Returns true for properties that are accessors to object fields.
83// If true, *object_offset contains offset of object field.
84template <class T>
85bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
86                                        Handle<Name> name,
87                                        int* object_offset) {
88  Isolate* isolate = name->GetIsolate();
89
90  if (type->Is(T::String())) {
91    return CheckForName(name, isolate->factory()->length_string(),
92                        String::kLengthOffset, object_offset);
93  }
94
95  if (!type->IsClass()) return false;
96  Handle<Map> map = type->AsClass()->Map();
97
98  switch (map->instance_type()) {
99    case JS_ARRAY_TYPE:
100      return
101        CheckForName(name, isolate->factory()->length_string(),
102                     JSArray::kLengthOffset, object_offset);
103    case JS_TYPED_ARRAY_TYPE:
104      return
105        CheckForName(name, isolate->factory()->length_string(),
106                     JSTypedArray::kLengthOffset, object_offset) ||
107        CheckForName(name, isolate->factory()->byte_length_string(),
108                     JSTypedArray::kByteLengthOffset, object_offset) ||
109        CheckForName(name, isolate->factory()->byte_offset_string(),
110                     JSTypedArray::kByteOffsetOffset, object_offset);
111    case JS_ARRAY_BUFFER_TYPE:
112      return
113        CheckForName(name, isolate->factory()->byte_length_string(),
114                     JSArrayBuffer::kByteLengthOffset, object_offset);
115    case JS_DATA_VIEW_TYPE:
116      return
117        CheckForName(name, isolate->factory()->byte_length_string(),
118                     JSDataView::kByteLengthOffset, object_offset) ||
119        CheckForName(name, isolate->factory()->byte_offset_string(),
120                     JSDataView::kByteOffsetOffset, object_offset);
121    default:
122      return false;
123  }
124}
125
126
127template
128bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
129                                              Handle<Name> name,
130                                              int* object_offset);
131
132
133template
134bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
135                                                  Handle<Name> name,
136                                                  int* object_offset);
137
138
139bool SetPropertyOnInstanceIfInherited(
140    Isolate* isolate, const v8::PropertyCallbackInfo<void>& info,
141    v8::Local<v8::Name> name, Handle<Object> value) {
142  Handle<Object> holder = Utils::OpenHandle(*info.Holder());
143  Handle<Object> receiver = Utils::OpenHandle(*info.This());
144  if (*holder == *receiver) return false;
145  if (receiver->IsJSObject()) {
146    Handle<JSObject> object = Handle<JSObject>::cast(receiver);
147    // This behaves sloppy since we lost the actual strict-mode.
148    // TODO(verwaest): Fix by making ExecutableAccessorInfo behave like data
149    // properties.
150    if (!object->map()->is_extensible()) return true;
151    JSObject::SetOwnPropertyIgnoreAttributes(object, Utils::OpenHandle(*name),
152                                             value, NONE).Check();
153  }
154  return true;
155}
156
157
158//
159// Accessors::ArgumentsIterator
160//
161
162
163void Accessors::ArgumentsIteratorGetter(
164    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
165  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
166  DisallowHeapAllocation no_allocation;
167  HandleScope scope(isolate);
168  Object* result = isolate->native_context()->array_values_iterator();
169  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
170}
171
172
173void Accessors::ArgumentsIteratorSetter(
174    v8::Local<v8::Name> name, v8::Local<v8::Value> val,
175    const v8::PropertyCallbackInfo<void>& info) {
176  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
177  HandleScope scope(isolate);
178  Handle<JSObject> object = Utils::OpenHandle(*info.This());
179  Handle<Object> value = Utils::OpenHandle(*val);
180
181  if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) return;
182
183  LookupIterator it(object, Utils::OpenHandle(*name));
184  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
185  DCHECK(it.HolderIsReceiverOrHiddenPrototype());
186  Object::SetDataProperty(&it, value);
187}
188
189
190Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
191    Isolate* isolate, PropertyAttributes attributes) {
192  Handle<Name> name(isolate->native_context()->iterator_symbol(), isolate);
193  return MakeAccessor(isolate, name, &ArgumentsIteratorGetter,
194                      &ArgumentsIteratorSetter, attributes);
195}
196
197
198//
199// Accessors::ArrayLength
200//
201
202
203// The helper function will 'flatten' Number objects.
204Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
205                                        Handle<Object> value) {
206  if (value->IsNumber() || !value->IsJSValue()) return value;
207  Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
208  DCHECK(wrapper->GetIsolate()->native_context()->number_function()->
209      has_initial_map());
210  if (wrapper->map() == isolate->number_function()->initial_map()) {
211    return handle(wrapper->value(), isolate);
212  }
213
214  return value;
215}
216
217
218void Accessors::ArrayLengthGetter(
219    v8::Local<v8::Name> name,
220    const v8::PropertyCallbackInfo<v8::Value>& info) {
221  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
222  DisallowHeapAllocation no_allocation;
223  HandleScope scope(isolate);
224  JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
225  Object* result = holder->length();
226  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
227}
228
229
230void Accessors::ArrayLengthSetter(
231    v8::Local<v8::Name> name,
232    v8::Local<v8::Value> val,
233    const v8::PropertyCallbackInfo<void>& info) {
234  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
235  HandleScope scope(isolate);
236  Handle<JSObject> object = Utils::OpenHandle(*info.This());
237  Handle<Object> value = Utils::OpenHandle(*val);
238  if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
239    return;
240  }
241
242  value = FlattenNumber(isolate, value);
243
244  Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
245  MaybeHandle<Object> maybe;
246  Handle<Object> uint32_v;
247  maybe = Execution::ToUint32(isolate, value);
248  if (!maybe.ToHandle(&uint32_v)) {
249    isolate->OptionalRescheduleException(false);
250    return;
251  }
252  Handle<Object> number_v;
253  maybe = Execution::ToNumber(isolate, value);
254  if (!maybe.ToHandle(&number_v)) {
255    isolate->OptionalRescheduleException(false);
256    return;
257  }
258
259  if (uint32_v->Number() == number_v->Number()) {
260    maybe = JSArray::SetElementsLength(array_handle, uint32_v);
261    maybe.Check();
262    return;
263  }
264
265  Handle<Object> exception;
266  maybe = isolate->factory()->NewRangeError("invalid_array_length",
267                                            HandleVector<Object>(NULL, 0));
268  if (!maybe.ToHandle(&exception)) {
269    isolate->OptionalRescheduleException(false);
270    return;
271  }
272
273  isolate->ScheduleThrow(*exception);
274}
275
276
277Handle<AccessorInfo> Accessors::ArrayLengthInfo(
278      Isolate* isolate, PropertyAttributes attributes) {
279  return MakeAccessor(isolate,
280                      isolate->factory()->length_string(),
281                      &ArrayLengthGetter,
282                      &ArrayLengthSetter,
283                      attributes);
284}
285
286
287
288//
289// Accessors::StringLength
290//
291
292void Accessors::StringLengthGetter(
293    v8::Local<v8::Name> name,
294    const v8::PropertyCallbackInfo<v8::Value>& info) {
295  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
296  DisallowHeapAllocation no_allocation;
297  HandleScope scope(isolate);
298
299  // We have a slight impedance mismatch between the external API and the way we
300  // use callbacks internally: Externally, callbacks can only be used with
301  // v8::Object, but internally we have callbacks on entities which are higher
302  // in the hierarchy, in this case for String values.
303
304  Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
305  if (!value->IsString()) {
306    // Not a string value. That means that we either got a String wrapper or
307    // a Value with a String wrapper in its prototype chain.
308    value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
309  }
310  Object* result = Smi::FromInt(String::cast(value)->length());
311  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
312}
313
314
315void Accessors::StringLengthSetter(
316    v8::Local<v8::Name> name,
317    v8::Local<v8::Value> value,
318    const v8::PropertyCallbackInfo<void>& info) {
319  UNREACHABLE();
320}
321
322
323Handle<AccessorInfo> Accessors::StringLengthInfo(
324      Isolate* isolate, PropertyAttributes attributes) {
325  return MakeAccessor(isolate,
326                      isolate->factory()->length_string(),
327                      &StringLengthGetter,
328                      &StringLengthSetter,
329                      attributes);
330}
331
332
333//
334// Accessors::ScriptColumnOffset
335//
336
337
338void Accessors::ScriptColumnOffsetGetter(
339    v8::Local<v8::Name> name,
340    const v8::PropertyCallbackInfo<v8::Value>& info) {
341  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
342  DisallowHeapAllocation no_allocation;
343  HandleScope scope(isolate);
344  Object* object = *Utils::OpenHandle(*info.This());
345  Object* res = Script::cast(JSValue::cast(object)->value())->column_offset();
346  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
347}
348
349
350void Accessors::ScriptColumnOffsetSetter(
351    v8::Local<v8::Name> name,
352    v8::Local<v8::Value> value,
353    const v8::PropertyCallbackInfo<void>& info) {
354  UNREACHABLE();
355}
356
357
358Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
359      Isolate* isolate, PropertyAttributes attributes) {
360  Handle<String> name(isolate->factory()->InternalizeOneByteString(
361      STATIC_CHAR_VECTOR("column_offset")));
362  return MakeAccessor(isolate,
363                      name,
364                      &ScriptColumnOffsetGetter,
365                      &ScriptColumnOffsetSetter,
366                      attributes);
367}
368
369
370//
371// Accessors::ScriptId
372//
373
374
375void Accessors::ScriptIdGetter(
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.This());
382  Object* id = Script::cast(JSValue::cast(object)->value())->id();
383  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
384}
385
386
387void Accessors::ScriptIdSetter(
388    v8::Local<v8::Name> name,
389    v8::Local<v8::Value> value,
390    const v8::PropertyCallbackInfo<void>& info) {
391  UNREACHABLE();
392}
393
394
395Handle<AccessorInfo> Accessors::ScriptIdInfo(
396      Isolate* isolate, PropertyAttributes attributes) {
397  Handle<String> name(
398      isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
399  return MakeAccessor(isolate,
400                      name,
401                      &ScriptIdGetter,
402                      &ScriptIdSetter,
403                      attributes);
404}
405
406
407//
408// Accessors::ScriptName
409//
410
411
412void Accessors::ScriptNameGetter(
413    v8::Local<v8::Name> name,
414    const v8::PropertyCallbackInfo<v8::Value>& info) {
415  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
416  DisallowHeapAllocation no_allocation;
417  HandleScope scope(isolate);
418  Object* object = *Utils::OpenHandle(*info.This());
419  Object* source = Script::cast(JSValue::cast(object)->value())->name();
420  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
421}
422
423
424void Accessors::ScriptNameSetter(
425    v8::Local<v8::Name> name,
426    v8::Local<v8::Value> value,
427    const v8::PropertyCallbackInfo<void>& info) {
428  UNREACHABLE();
429}
430
431
432Handle<AccessorInfo> Accessors::ScriptNameInfo(
433      Isolate* isolate, PropertyAttributes attributes) {
434  return MakeAccessor(isolate,
435                      isolate->factory()->name_string(),
436                      &ScriptNameGetter,
437                      &ScriptNameSetter,
438                      attributes);
439}
440
441
442//
443// Accessors::ScriptSource
444//
445
446
447void Accessors::ScriptSourceGetter(
448    v8::Local<v8::Name> name,
449    const v8::PropertyCallbackInfo<v8::Value>& info) {
450  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
451  DisallowHeapAllocation no_allocation;
452  HandleScope scope(isolate);
453  Object* object = *Utils::OpenHandle(*info.This());
454  Object* source = Script::cast(JSValue::cast(object)->value())->source();
455  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
456}
457
458
459void Accessors::ScriptSourceSetter(
460    v8::Local<v8::Name> name,
461    v8::Local<v8::Value> value,
462    const v8::PropertyCallbackInfo<void>& info) {
463  UNREACHABLE();
464}
465
466
467Handle<AccessorInfo> Accessors::ScriptSourceInfo(
468      Isolate* isolate, PropertyAttributes attributes) {
469  return MakeAccessor(isolate,
470                      isolate->factory()->source_string(),
471                      &ScriptSourceGetter,
472                      &ScriptSourceSetter,
473                      attributes);
474}
475
476
477//
478// Accessors::ScriptLineOffset
479//
480
481
482void Accessors::ScriptLineOffsetGetter(
483    v8::Local<v8::Name> name,
484    const v8::PropertyCallbackInfo<v8::Value>& info) {
485  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
486  DisallowHeapAllocation no_allocation;
487  HandleScope scope(isolate);
488  Object* object = *Utils::OpenHandle(*info.This());
489  Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
490  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
491}
492
493
494void Accessors::ScriptLineOffsetSetter(
495    v8::Local<v8::Name> name,
496    v8::Local<v8::Value> value,
497    const v8::PropertyCallbackInfo<void>& info) {
498  UNREACHABLE();
499}
500
501
502Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
503      Isolate* isolate, PropertyAttributes attributes) {
504  Handle<String> name(isolate->factory()->InternalizeOneByteString(
505      STATIC_CHAR_VECTOR("line_offset")));
506  return MakeAccessor(isolate,
507                      name,
508                      &ScriptLineOffsetGetter,
509                      &ScriptLineOffsetSetter,
510                      attributes);
511}
512
513
514//
515// Accessors::ScriptType
516//
517
518
519void Accessors::ScriptTypeGetter(
520    v8::Local<v8::Name> name,
521    const v8::PropertyCallbackInfo<v8::Value>& info) {
522  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
523  DisallowHeapAllocation no_allocation;
524  HandleScope scope(isolate);
525  Object* object = *Utils::OpenHandle(*info.This());
526  Object* res = Script::cast(JSValue::cast(object)->value())->type();
527  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
528}
529
530
531void Accessors::ScriptTypeSetter(
532    v8::Local<v8::Name> name,
533    v8::Local<v8::Value> value,
534    const v8::PropertyCallbackInfo<void>& info) {
535  UNREACHABLE();
536}
537
538
539Handle<AccessorInfo> Accessors::ScriptTypeInfo(
540      Isolate* isolate, PropertyAttributes attributes) {
541  Handle<String> name(
542      isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
543  return MakeAccessor(isolate,
544                      name,
545                      &ScriptTypeGetter,
546                      &ScriptTypeSetter,
547                      attributes);
548}
549
550
551//
552// Accessors::ScriptCompilationType
553//
554
555
556void Accessors::ScriptCompilationTypeGetter(
557    v8::Local<v8::Name> name,
558    const v8::PropertyCallbackInfo<v8::Value>& info) {
559  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
560  DisallowHeapAllocation no_allocation;
561  HandleScope scope(isolate);
562  Object* object = *Utils::OpenHandle(*info.This());
563  Object* res = Smi::FromInt(
564      Script::cast(JSValue::cast(object)->value())->compilation_type());
565  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
566}
567
568
569void Accessors::ScriptCompilationTypeSetter(
570    v8::Local<v8::Name> name,
571    v8::Local<v8::Value> value,
572    const v8::PropertyCallbackInfo<void>& info) {
573  UNREACHABLE();
574}
575
576
577Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
578      Isolate* isolate, PropertyAttributes attributes) {
579  Handle<String> name(isolate->factory()->InternalizeOneByteString(
580      STATIC_CHAR_VECTOR("compilation_type")));
581  return MakeAccessor(isolate,
582                      name,
583                      &ScriptCompilationTypeGetter,
584                      &ScriptCompilationTypeSetter,
585                      attributes);
586}
587
588
589//
590// Accessors::ScriptGetLineEnds
591//
592
593
594void Accessors::ScriptLineEndsGetter(
595    v8::Local<v8::Name> name,
596    const v8::PropertyCallbackInfo<v8::Value>& info) {
597  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
598  HandleScope scope(isolate);
599  Handle<Object> object = Utils::OpenHandle(*info.This());
600  Handle<Script> script(
601      Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
602  Script::InitLineEnds(script);
603  DCHECK(script->line_ends()->IsFixedArray());
604  Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
605  // We do not want anyone to modify this array from JS.
606  DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
607         line_ends->map() == isolate->heap()->fixed_cow_array_map());
608  Handle<JSArray> js_array =
609      isolate->factory()->NewJSArrayWithElements(line_ends);
610  info.GetReturnValue().Set(Utils::ToLocal(js_array));
611}
612
613
614void Accessors::ScriptLineEndsSetter(
615    v8::Local<v8::Name> name,
616    v8::Local<v8::Value> value,
617    const v8::PropertyCallbackInfo<void>& info) {
618  UNREACHABLE();
619}
620
621
622Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
623      Isolate* isolate, PropertyAttributes attributes) {
624  Handle<String> name(isolate->factory()->InternalizeOneByteString(
625      STATIC_CHAR_VECTOR("line_ends")));
626  return MakeAccessor(isolate,
627                      name,
628                      &ScriptLineEndsGetter,
629                      &ScriptLineEndsSetter,
630                      attributes);
631}
632
633
634//
635// Accessors::ScriptSourceUrl
636//
637
638
639void Accessors::ScriptSourceUrlGetter(
640    v8::Local<v8::Name> name,
641    const v8::PropertyCallbackInfo<v8::Value>& info) {
642  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
643  DisallowHeapAllocation no_allocation;
644  HandleScope scope(isolate);
645  Object* object = *Utils::OpenHandle(*info.This());
646  Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
647  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
648}
649
650
651void Accessors::ScriptSourceUrlSetter(
652    v8::Local<v8::Name> name,
653    v8::Local<v8::Value> value,
654    const v8::PropertyCallbackInfo<void>& info) {
655  UNREACHABLE();
656}
657
658
659Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
660      Isolate* isolate, PropertyAttributes attributes) {
661  return MakeAccessor(isolate,
662                      isolate->factory()->source_url_string(),
663                      &ScriptSourceUrlGetter,
664                      &ScriptSourceUrlSetter,
665                      attributes);
666}
667
668
669//
670// Accessors::ScriptSourceMappingUrl
671//
672
673
674void Accessors::ScriptSourceMappingUrlGetter(
675    v8::Local<v8::Name> name,
676    const v8::PropertyCallbackInfo<v8::Value>& info) {
677  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
678  DisallowHeapAllocation no_allocation;
679  HandleScope scope(isolate);
680  Object* object = *Utils::OpenHandle(*info.This());
681  Object* url =
682      Script::cast(JSValue::cast(object)->value())->source_mapping_url();
683  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
684}
685
686
687void Accessors::ScriptSourceMappingUrlSetter(
688    v8::Local<v8::Name> name,
689    v8::Local<v8::Value> value,
690    const v8::PropertyCallbackInfo<void>& info) {
691  UNREACHABLE();
692}
693
694
695Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
696      Isolate* isolate, PropertyAttributes attributes) {
697  return MakeAccessor(isolate,
698                      isolate->factory()->source_mapping_url_string(),
699                      &ScriptSourceMappingUrlGetter,
700                      &ScriptSourceMappingUrlSetter,
701                      attributes);
702}
703
704
705//
706// Accessors::ScriptGetContextData
707//
708
709
710void Accessors::ScriptContextDataGetter(
711    v8::Local<v8::Name> name,
712    const v8::PropertyCallbackInfo<v8::Value>& info) {
713  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
714  DisallowHeapAllocation no_allocation;
715  HandleScope scope(isolate);
716  Object* object = *Utils::OpenHandle(*info.This());
717  Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
718  info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
719}
720
721
722void Accessors::ScriptContextDataSetter(
723    v8::Local<v8::Name> name,
724    v8::Local<v8::Value> value,
725    const v8::PropertyCallbackInfo<void>& info) {
726  UNREACHABLE();
727}
728
729
730Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
731      Isolate* isolate, PropertyAttributes attributes) {
732  Handle<String> name(isolate->factory()->InternalizeOneByteString(
733      STATIC_CHAR_VECTOR("context_data")));
734  return MakeAccessor(isolate,
735                      name,
736                      &ScriptContextDataGetter,
737                      &ScriptContextDataSetter,
738                      attributes);
739}
740
741
742//
743// Accessors::ScriptGetEvalFromScript
744//
745
746
747void Accessors::ScriptEvalFromScriptGetter(
748    v8::Local<v8::Name> name,
749    const v8::PropertyCallbackInfo<v8::Value>& info) {
750  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
751  HandleScope scope(isolate);
752  Handle<Object> object = Utils::OpenHandle(*info.This());
753  Handle<Script> script(
754      Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
755  Handle<Object> result = isolate->factory()->undefined_value();
756  if (!script->eval_from_shared()->IsUndefined()) {
757    Handle<SharedFunctionInfo> eval_from_shared(
758        SharedFunctionInfo::cast(script->eval_from_shared()));
759    if (eval_from_shared->script()->IsScript()) {
760      Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
761      result = Script::GetWrapper(eval_from_script);
762    }
763  }
764
765  info.GetReturnValue().Set(Utils::ToLocal(result));
766}
767
768
769void Accessors::ScriptEvalFromScriptSetter(
770    v8::Local<v8::Name> name,
771    v8::Local<v8::Value> value,
772    const v8::PropertyCallbackInfo<void>& info) {
773  UNREACHABLE();
774}
775
776
777Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
778      Isolate* isolate, PropertyAttributes attributes) {
779  Handle<String> name(isolate->factory()->InternalizeOneByteString(
780      STATIC_CHAR_VECTOR("eval_from_script")));
781  return MakeAccessor(isolate,
782                      name,
783                      &ScriptEvalFromScriptGetter,
784                      &ScriptEvalFromScriptSetter,
785                      attributes);
786}
787
788
789//
790// Accessors::ScriptGetEvalFromScriptPosition
791//
792
793
794void Accessors::ScriptEvalFromScriptPositionGetter(
795    v8::Local<v8::Name> name,
796    const v8::PropertyCallbackInfo<v8::Value>& info) {
797  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
798  HandleScope scope(isolate);
799  Handle<Object> object = Utils::OpenHandle(*info.This());
800  Handle<Script> script(
801      Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
802  Handle<Object> result = isolate->factory()->undefined_value();
803  if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
804    Handle<Code> code(SharedFunctionInfo::cast(
805        script->eval_from_shared())->code());
806    result = Handle<Object>(
807        Smi::FromInt(code->SourcePosition(code->instruction_start() +
808                     script->eval_from_instructions_offset()->value())),
809        isolate);
810  }
811  info.GetReturnValue().Set(Utils::ToLocal(result));
812}
813
814
815void Accessors::ScriptEvalFromScriptPositionSetter(
816    v8::Local<v8::Name> name,
817    v8::Local<v8::Value> value,
818    const v8::PropertyCallbackInfo<void>& info) {
819  UNREACHABLE();
820}
821
822
823Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
824      Isolate* isolate, PropertyAttributes attributes) {
825  Handle<String> name(isolate->factory()->InternalizeOneByteString(
826      STATIC_CHAR_VECTOR("eval_from_script_position")));
827  return MakeAccessor(isolate,
828                      name,
829                      &ScriptEvalFromScriptPositionGetter,
830                      &ScriptEvalFromScriptPositionSetter,
831                      attributes);
832}
833
834
835//
836// Accessors::ScriptGetEvalFromFunctionName
837//
838
839
840void Accessors::ScriptEvalFromFunctionNameGetter(
841    v8::Local<v8::Name> name,
842    const v8::PropertyCallbackInfo<v8::Value>& info) {
843  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
844  HandleScope scope(isolate);
845  Handle<Object> object = Utils::OpenHandle(*info.This());
846  Handle<Script> script(
847      Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
848  Handle<Object> result;
849  Handle<SharedFunctionInfo> shared(
850      SharedFunctionInfo::cast(script->eval_from_shared()));
851  // Find the name of the function calling eval.
852  if (!shared->name()->IsUndefined()) {
853    result = Handle<Object>(shared->name(), isolate);
854  } else {
855    result = Handle<Object>(shared->inferred_name(), isolate);
856  }
857  info.GetReturnValue().Set(Utils::ToLocal(result));
858}
859
860
861void Accessors::ScriptEvalFromFunctionNameSetter(
862    v8::Local<v8::Name> name,
863    v8::Local<v8::Value> value,
864    const v8::PropertyCallbackInfo<void>& info) {
865  UNREACHABLE();
866}
867
868
869Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
870      Isolate* isolate, PropertyAttributes attributes) {
871  Handle<String> name(isolate->factory()->InternalizeOneByteString(
872      STATIC_CHAR_VECTOR("eval_from_function_name")));
873  return MakeAccessor(isolate,
874                      name,
875                      &ScriptEvalFromFunctionNameGetter,
876                      &ScriptEvalFromFunctionNameSetter,
877                      attributes);
878}
879
880
881//
882// Accessors::FunctionPrototype
883//
884
885static Handle<Object> GetFunctionPrototype(Isolate* isolate,
886                                           Handle<JSFunction> function) {
887  if (!function->has_prototype()) {
888    Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
889    JSFunction::SetPrototype(function, proto);
890  }
891  return Handle<Object>(function->prototype(), isolate);
892}
893
894
895static Handle<Object> SetFunctionPrototype(Isolate* isolate,
896                                           Handle<JSFunction> function,
897                                           Handle<Object> value) {
898  Handle<Object> old_value;
899  bool is_observed = function->map()->is_observed();
900  if (is_observed) {
901    if (function->has_prototype())
902      old_value = handle(function->prototype(), isolate);
903    else
904      old_value = isolate->factory()->NewFunctionPrototype(function);
905  }
906
907  JSFunction::SetPrototype(function, value);
908  DCHECK(function->prototype() == *value);
909
910  if (is_observed && !old_value->SameValue(*value)) {
911    JSObject::EnqueueChangeRecord(
912        function, "update", isolate->factory()->prototype_string(), old_value);
913  }
914
915  return function;
916}
917
918
919Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
920  return GetFunctionPrototype(function->GetIsolate(), function);
921}
922
923
924Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
925                                               Handle<Object> prototype) {
926  DCHECK(function->should_have_prototype());
927  Isolate* isolate = function->GetIsolate();
928  return SetFunctionPrototype(isolate, function, prototype);
929}
930
931
932void Accessors::FunctionPrototypeGetter(
933    v8::Local<v8::Name> name,
934    const v8::PropertyCallbackInfo<v8::Value>& info) {
935  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
936  HandleScope scope(isolate);
937  Handle<JSFunction> function =
938      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
939  Handle<Object> result = GetFunctionPrototype(isolate, function);
940  info.GetReturnValue().Set(Utils::ToLocal(result));
941}
942
943
944void Accessors::FunctionPrototypeSetter(
945    v8::Local<v8::Name> name,
946    v8::Local<v8::Value> val,
947    const v8::PropertyCallbackInfo<void>& info) {
948  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
949  HandleScope scope(isolate);
950  Handle<Object> value = Utils::OpenHandle(*val);
951  if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
952    return;
953  }
954  Handle<JSFunction> object =
955      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
956  SetFunctionPrototype(isolate, object, value);
957}
958
959
960Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
961      Isolate* isolate, PropertyAttributes attributes) {
962  return MakeAccessor(isolate,
963                      isolate->factory()->prototype_string(),
964                      &FunctionPrototypeGetter,
965                      &FunctionPrototypeSetter,
966                      attributes);
967}
968
969
970//
971// Accessors::FunctionLength
972//
973
974
975void Accessors::FunctionLengthGetter(
976    v8::Local<v8::Name> name,
977    const v8::PropertyCallbackInfo<v8::Value>& info) {
978  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
979  HandleScope scope(isolate);
980  Handle<JSFunction> function =
981      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
982
983  int length = 0;
984  if (function->shared()->is_compiled()) {
985    length = function->shared()->length();
986  } else {
987    // If the function isn't compiled yet, the length is not computed
988    // correctly yet. Compile it now and return the right length.
989    if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
990      length = function->shared()->length();
991    }
992    if (isolate->has_pending_exception()) {
993      isolate->OptionalRescheduleException(false);
994    }
995  }
996  Handle<Object> result(Smi::FromInt(length), isolate);
997  info.GetReturnValue().Set(Utils::ToLocal(result));
998}
999
1000
1001void Accessors::FunctionLengthSetter(
1002    v8::Local<v8::Name> name,
1003    v8::Local<v8::Value> val,
1004    const v8::PropertyCallbackInfo<void>& info) {
1005  // Function length is non writable, non configurable.
1006  UNREACHABLE();
1007}
1008
1009
1010Handle<AccessorInfo> Accessors::FunctionLengthInfo(
1011      Isolate* isolate, PropertyAttributes attributes) {
1012  return MakeAccessor(isolate,
1013                      isolate->factory()->length_string(),
1014                      &FunctionLengthGetter,
1015                      &FunctionLengthSetter,
1016                      attributes);
1017}
1018
1019
1020//
1021// Accessors::FunctionName
1022//
1023
1024
1025void Accessors::FunctionNameGetter(
1026    v8::Local<v8::Name> name,
1027    const v8::PropertyCallbackInfo<v8::Value>& info) {
1028  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1029  HandleScope scope(isolate);
1030  Handle<JSFunction> function =
1031      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1032  Handle<Object> result(function->shared()->name(), isolate);
1033  info.GetReturnValue().Set(Utils::ToLocal(result));
1034}
1035
1036
1037void Accessors::FunctionNameSetter(
1038    v8::Local<v8::Name> name,
1039    v8::Local<v8::Value> val,
1040    const v8::PropertyCallbackInfo<void>& info) {
1041  // Function name is non writable, non configurable.
1042  UNREACHABLE();
1043}
1044
1045
1046Handle<AccessorInfo> Accessors::FunctionNameInfo(
1047      Isolate* isolate, PropertyAttributes attributes) {
1048  return MakeAccessor(isolate,
1049                      isolate->factory()->name_string(),
1050                      &FunctionNameGetter,
1051                      &FunctionNameSetter,
1052                      attributes);
1053}
1054
1055
1056//
1057// Accessors::FunctionArguments
1058//
1059
1060
1061static Handle<Object> ArgumentsForInlinedFunction(
1062    JavaScriptFrame* frame,
1063    Handle<JSFunction> inlined_function,
1064    int inlined_frame_index) {
1065  Isolate* isolate = inlined_function->GetIsolate();
1066  Factory* factory = isolate->factory();
1067  SlotRefValueBuilder slot_refs(
1068      frame,
1069      inlined_frame_index,
1070      inlined_function->shared()->formal_parameter_count());
1071
1072  int args_count = slot_refs.args_length();
1073  Handle<JSObject> arguments =
1074      factory->NewArgumentsObject(inlined_function, args_count);
1075  Handle<FixedArray> array = factory->NewFixedArray(args_count);
1076  slot_refs.Prepare(isolate);
1077  for (int i = 0; i < args_count; ++i) {
1078    Handle<Object> value = slot_refs.GetNext(isolate, 0);
1079    array->set(i, *value);
1080  }
1081  slot_refs.Finish(isolate);
1082  arguments->set_elements(*array);
1083
1084  // Return the freshly allocated arguments object.
1085  return arguments;
1086}
1087
1088
1089static int FindFunctionInFrame(JavaScriptFrame* frame,
1090                               Handle<JSFunction> function) {
1091  DisallowHeapAllocation no_allocation;
1092  List<JSFunction*> functions(2);
1093  frame->GetFunctions(&functions);
1094  for (int i = functions.length() - 1; i >= 0; i--) {
1095    if (functions[i] == *function) return i;
1096  }
1097  return -1;
1098}
1099
1100
1101Handle<Object> GetFunctionArguments(Isolate* isolate,
1102                                    Handle<JSFunction> function) {
1103  if (function->shared()->native()) return isolate->factory()->null_value();
1104
1105  // Find the top invocation of the function by traversing frames.
1106  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
1107    JavaScriptFrame* frame = it.frame();
1108    int function_index = FindFunctionInFrame(frame, function);
1109    if (function_index < 0) continue;
1110
1111    if (function_index > 0) {
1112      // The function in question was inlined.  Inlined functions have the
1113      // correct number of arguments and no allocated arguments object, so
1114      // we can construct a fresh one by interpreting the function's
1115      // deoptimization input data.
1116      return ArgumentsForInlinedFunction(frame, function, function_index);
1117    }
1118
1119    if (!frame->is_optimized()) {
1120      // If there is an arguments variable in the stack, we return that.
1121      Handle<ScopeInfo> scope_info(function->shared()->scope_info());
1122      int index = scope_info->StackSlotIndex(
1123          isolate->heap()->arguments_string());
1124      if (index >= 0) {
1125        Handle<Object> arguments(frame->GetExpression(index), isolate);
1126        if (!arguments->IsArgumentsMarker()) return arguments;
1127      }
1128    }
1129
1130    // If there is no arguments variable in the stack or we have an
1131    // optimized frame, we find the frame that holds the actual arguments
1132    // passed to the function.
1133    it.AdvanceToArgumentsFrame();
1134    frame = it.frame();
1135
1136    // Get the number of arguments and construct an arguments object
1137    // mirror for the right frame.
1138    const int length = frame->ComputeParametersCount();
1139    Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
1140        function, length);
1141    Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
1142
1143    // Copy the parameters to the arguments object.
1144    DCHECK(array->length() == length);
1145    for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
1146    arguments->set_elements(*array);
1147
1148    // Return the freshly allocated arguments object.
1149    return arguments;
1150  }
1151
1152  // No frame corresponding to the given function found. Return null.
1153  return isolate->factory()->null_value();
1154}
1155
1156
1157Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
1158  return GetFunctionArguments(function->GetIsolate(), function);
1159}
1160
1161
1162void Accessors::FunctionArgumentsGetter(
1163    v8::Local<v8::Name> name,
1164    const v8::PropertyCallbackInfo<v8::Value>& info) {
1165  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1166  HandleScope scope(isolate);
1167  Handle<JSFunction> function =
1168      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1169  Handle<Object> result = GetFunctionArguments(isolate, function);
1170  info.GetReturnValue().Set(Utils::ToLocal(result));
1171}
1172
1173
1174void Accessors::FunctionArgumentsSetter(
1175    v8::Local<v8::Name> name,
1176    v8::Local<v8::Value> val,
1177    const v8::PropertyCallbackInfo<void>& info) {
1178  // Function arguments is non writable, non configurable.
1179  UNREACHABLE();
1180}
1181
1182
1183Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
1184      Isolate* isolate, PropertyAttributes attributes) {
1185  return MakeAccessor(isolate,
1186                      isolate->factory()->arguments_string(),
1187                      &FunctionArgumentsGetter,
1188                      &FunctionArgumentsSetter,
1189                      attributes);
1190}
1191
1192
1193//
1194// Accessors::FunctionCaller
1195//
1196
1197
1198static inline bool AllowAccessToFunction(Context* current_context,
1199                                         JSFunction* function) {
1200  return current_context->HasSameSecurityTokenAs(function->context());
1201}
1202
1203
1204class FrameFunctionIterator {
1205 public:
1206  FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
1207      : isolate_(isolate),
1208        frame_iterator_(isolate),
1209        functions_(2),
1210        index_(0) {
1211    GetFunctions();
1212  }
1213  JSFunction* next() {
1214    while (true) {
1215      if (functions_.length() == 0) return NULL;
1216      JSFunction* next_function = functions_[index_];
1217      index_--;
1218      if (index_ < 0) {
1219        GetFunctions();
1220      }
1221      // Skip functions from other origins.
1222      if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
1223      return next_function;
1224    }
1225  }
1226
1227  // Iterate through functions until the first occurence of 'function'.
1228  // Returns true if 'function' is found, and false if the iterator ends
1229  // without finding it.
1230  bool Find(JSFunction* function) {
1231    JSFunction* next_function;
1232    do {
1233      next_function = next();
1234      if (next_function == function) return true;
1235    } while (next_function != NULL);
1236    return false;
1237  }
1238
1239 private:
1240  void GetFunctions() {
1241    functions_.Rewind(0);
1242    if (frame_iterator_.done()) return;
1243    JavaScriptFrame* frame = frame_iterator_.frame();
1244    frame->GetFunctions(&functions_);
1245    DCHECK(functions_.length() > 0);
1246    frame_iterator_.Advance();
1247    index_ = functions_.length() - 1;
1248  }
1249  Isolate* isolate_;
1250  JavaScriptFrameIterator frame_iterator_;
1251  List<JSFunction*> functions_;
1252  int index_;
1253};
1254
1255
1256MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
1257                                   Handle<JSFunction> function) {
1258  DisallowHeapAllocation no_allocation;
1259  FrameFunctionIterator it(isolate, no_allocation);
1260  if (function->shared()->native()) {
1261    return MaybeHandle<JSFunction>();
1262  }
1263  // Find the function from the frames.
1264  if (!it.Find(*function)) {
1265    // No frame corresponding to the given function found. Return null.
1266    return MaybeHandle<JSFunction>();
1267  }
1268  // Find previously called non-toplevel function.
1269  JSFunction* caller;
1270  do {
1271    caller = it.next();
1272    if (caller == NULL) return MaybeHandle<JSFunction>();
1273  } while (caller->shared()->is_toplevel());
1274
1275  // If caller is a built-in function and caller's caller is also built-in,
1276  // use that instead.
1277  JSFunction* potential_caller = caller;
1278  while (potential_caller != NULL && potential_caller->IsBuiltin()) {
1279    caller = potential_caller;
1280    potential_caller = it.next();
1281  }
1282  if (!caller->shared()->native() && potential_caller != NULL) {
1283    caller = potential_caller;
1284  }
1285  // If caller is bound, return null. This is compatible with JSC, and
1286  // allows us to make bound functions use the strict function map
1287  // and its associated throwing caller and arguments.
1288  if (caller->shared()->bound()) {
1289    return MaybeHandle<JSFunction>();
1290  }
1291  // Censor if the caller is not a sloppy mode function.
1292  // Change from ES5, which used to throw, see:
1293  // https://bugs.ecmascript.org/show_bug.cgi?id=310
1294  if (caller->shared()->strict_mode() == STRICT) {
1295    return MaybeHandle<JSFunction>();
1296  }
1297  // Don't return caller from another security context.
1298  if (!AllowAccessToFunction(isolate->context(), caller)) {
1299    return MaybeHandle<JSFunction>();
1300  }
1301  return Handle<JSFunction>(caller);
1302}
1303
1304
1305void Accessors::FunctionCallerGetter(
1306    v8::Local<v8::Name> name,
1307    const v8::PropertyCallbackInfo<v8::Value>& info) {
1308  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1309  HandleScope scope(isolate);
1310  Handle<JSFunction> function =
1311      Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1312  Handle<Object> result;
1313  MaybeHandle<JSFunction> maybe_caller;
1314  maybe_caller = FindCaller(isolate, function);
1315  Handle<JSFunction> caller;
1316  if (maybe_caller.ToHandle(&caller)) {
1317    result = caller;
1318  } else {
1319    result = isolate->factory()->null_value();
1320  }
1321  info.GetReturnValue().Set(Utils::ToLocal(result));
1322}
1323
1324
1325void Accessors::FunctionCallerSetter(
1326    v8::Local<v8::Name> name,
1327    v8::Local<v8::Value> val,
1328    const v8::PropertyCallbackInfo<void>& info) {
1329  // Function caller is non writable, non configurable.
1330  UNREACHABLE();
1331}
1332
1333
1334Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1335      Isolate* isolate, PropertyAttributes attributes) {
1336  return MakeAccessor(isolate,
1337                      isolate->factory()->caller_string(),
1338                      &FunctionCallerGetter,
1339                      &FunctionCallerSetter,
1340                      attributes);
1341}
1342
1343
1344//
1345// Accessors::MakeModuleExport
1346//
1347
1348static void ModuleGetExport(
1349    v8::Local<v8::String> property,
1350    const v8::PropertyCallbackInfo<v8::Value>& info) {
1351  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1352  Context* context = Context::cast(instance->context());
1353  DCHECK(context->IsModuleContext());
1354  int slot = info.Data()->Int32Value();
1355  Object* value = context->get(slot);
1356  Isolate* isolate = instance->GetIsolate();
1357  if (value->IsTheHole()) {
1358    Handle<String> name = v8::Utils::OpenHandle(*property);
1359
1360    Handle<Object> exception;
1361    MaybeHandle<Object> maybe = isolate->factory()->NewReferenceError(
1362        "not_defined", HandleVector(&name, 1));
1363    if (!maybe.ToHandle(&exception)) {
1364      isolate->OptionalRescheduleException(false);
1365      return;
1366    }
1367
1368    isolate->ScheduleThrow(*exception);
1369    return;
1370  }
1371  info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
1372}
1373
1374
1375static void ModuleSetExport(
1376    v8::Local<v8::String> property,
1377    v8::Local<v8::Value> value,
1378    const v8::PropertyCallbackInfo<v8::Value>& info) {
1379  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1380  Context* context = Context::cast(instance->context());
1381  DCHECK(context->IsModuleContext());
1382  int slot = info.Data()->Int32Value();
1383  Object* old_value = context->get(slot);
1384  Isolate* isolate = context->GetIsolate();
1385  if (old_value->IsTheHole()) {
1386    Handle<String> name = v8::Utils::OpenHandle(*property);
1387    Handle<Object> exception;
1388    MaybeHandle<Object> maybe = isolate->factory()->NewReferenceError(
1389        "not_defined", HandleVector(&name, 1));
1390    if (!maybe.ToHandle(&exception)) {
1391      isolate->OptionalRescheduleException(false);
1392      return;
1393    }
1394
1395    isolate->ScheduleThrow(*exception);
1396    return;
1397  }
1398  context->set(slot, *v8::Utils::OpenHandle(*value));
1399}
1400
1401
1402Handle<AccessorInfo> Accessors::MakeModuleExport(
1403    Handle<String> name,
1404    int index,
1405    PropertyAttributes attributes) {
1406  Isolate* isolate = name->GetIsolate();
1407  Factory* factory = isolate->factory();
1408  Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
1409  info->set_property_attributes(attributes);
1410  info->set_all_can_read(true);
1411  info->set_all_can_write(true);
1412  info->set_name(*name);
1413  info->set_data(Smi::FromInt(index));
1414  Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
1415  Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
1416  info->set_getter(*getter);
1417  if (!(attributes & ReadOnly)) info->set_setter(*setter);
1418  return info;
1419}
1420
1421
1422} }  // namespace v8::internal
1423