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
19namespace v8 {
20namespace internal {
21
22
23Handle<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
52static 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.
66bool 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
89namespace {
90
91MUST_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
110void 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
130void 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
140Handle<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
153void 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
165void 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
199Handle<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
213void 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
236Handle<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
248void 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
261Handle<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
275void 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
287Handle<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
300void 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
312Handle<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
324void 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
336Handle<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
348void 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
361Handle<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
375void 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
388Handle<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
401void 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
414Handle<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
428void 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
448Handle<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
462void 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
474Handle<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
486void 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
499Handle<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
511void 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
525Handle<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
539void 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
551Handle<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
565void 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
587Handle<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
601void 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
617Handle<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
631void 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
654Handle<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
667static 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
677MUST_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
685MaybeHandle<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
693void 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
705void 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
720Handle<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
735void 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
751Handle<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
764void 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
775Handle<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
788static 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
834static 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
846namespace {
847
848Handle<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
891Handle<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
899void 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
914Handle<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
926static inline bool AllowAccessToFunction(Context* current_context,
927                                         JSFunction* function) {
928  return current_context->HasSameSecurityTokenAs(function->context());
929}
930
931
932class FrameFunctionIterator {
933 public:
934  FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
935      : isolate_(isolate),
936        frame_iterator_(isolate),
937        functions_(2),
938        index_(0) {
939    GetFunctions();
940  }
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.
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:
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
984MaybeHandle<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
1027void 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
1047Handle<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
1058void 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
1081Handle<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
1092void 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
1106Handle<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
1117static 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
1147static 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
1159Handle<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