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
20 namespace v8 {
21 namespace internal {
22
23
MakeAccessor(Isolate * isolate,Handle<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,PropertyAttributes attributes)24 Handle<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
CloneAccessor(Isolate * isolate,Handle<ExecutableAccessorInfo> accessor)44 Handle<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
59 template <class C>
FindInstanceOf(Isolate * isolate,Object * obj)60 static 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
CheckForName(Handle<Name> name,Handle<String> property_name,int offset,int * object_offset)70 static 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.
84 template <class T>
IsJSObjectFieldAccessor(typename T::TypeHandle type,Handle<Name> name,int * object_offset)85 bool 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
127 template
128 bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
129 Handle<Name> name,
130 int* object_offset);
131
132
133 template
134 bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
135 Handle<Name> name,
136 int* object_offset);
137
138
SetPropertyOnInstanceIfInherited(Isolate * isolate,const v8::PropertyCallbackInfo<void> & info,v8::Local<v8::Name> name,Handle<Object> value)139 bool 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
ArgumentsIteratorGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)163 void 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
ArgumentsIteratorSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)173 void 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
ArgumentsIteratorInfo(Isolate * isolate,PropertyAttributes attributes)190 Handle<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.
FlattenNumber(Isolate * isolate,Handle<Object> value)204 Handle<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
ArrayLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)218 void 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
ArrayLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)230 void 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
ArrayLengthInfo(Isolate * isolate,PropertyAttributes attributes)277 Handle<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
StringLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)292 void 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
StringLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)315 void 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
StringLengthInfo(Isolate * isolate,PropertyAttributes attributes)323 Handle<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
ScriptColumnOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)338 void 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
ScriptColumnOffsetSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)350 void 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
ScriptColumnOffsetInfo(Isolate * isolate,PropertyAttributes attributes)358 Handle<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
ScriptIdGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)375 void 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
ScriptIdSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)387 void 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
ScriptIdInfo(Isolate * isolate,PropertyAttributes attributes)395 Handle<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
ScriptNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)412 void 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
ScriptNameSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)424 void 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
ScriptNameInfo(Isolate * isolate,PropertyAttributes attributes)432 Handle<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
ScriptSourceGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)447 void 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
ScriptSourceSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)459 void 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
ScriptSourceInfo(Isolate * isolate,PropertyAttributes attributes)467 Handle<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
ScriptLineOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)482 void 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
ScriptLineOffsetSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)494 void 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
ScriptLineOffsetInfo(Isolate * isolate,PropertyAttributes attributes)502 Handle<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
ScriptTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)519 void 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
ScriptTypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)531 void 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
ScriptTypeInfo(Isolate * isolate,PropertyAttributes attributes)539 Handle<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
ScriptCompilationTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)556 void 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
ScriptCompilationTypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)569 void 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
ScriptCompilationTypeInfo(Isolate * isolate,PropertyAttributes attributes)577 Handle<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
ScriptLineEndsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)594 void 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
ScriptLineEndsSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)614 void 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
ScriptLineEndsInfo(Isolate * isolate,PropertyAttributes attributes)622 Handle<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
ScriptSourceUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)639 void 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
ScriptSourceUrlSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)651 void 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
ScriptSourceUrlInfo(Isolate * isolate,PropertyAttributes attributes)659 Handle<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
ScriptSourceMappingUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)674 void 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
ScriptSourceMappingUrlSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)687 void 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
ScriptSourceMappingUrlInfo(Isolate * isolate,PropertyAttributes attributes)695 Handle<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
ScriptContextDataGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)710 void 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
ScriptContextDataSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)722 void 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
ScriptContextDataInfo(Isolate * isolate,PropertyAttributes attributes)730 Handle<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
ScriptEvalFromScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)747 void 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
ScriptEvalFromScriptSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)769 void 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
ScriptEvalFromScriptInfo(Isolate * isolate,PropertyAttributes attributes)777 Handle<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
ScriptEvalFromScriptPositionGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)794 void 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
ScriptEvalFromScriptPositionSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)815 void 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
ScriptEvalFromScriptPositionInfo(Isolate * isolate,PropertyAttributes attributes)823 Handle<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
ScriptEvalFromFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)840 void 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
ScriptEvalFromFunctionNameSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)861 void 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
ScriptEvalFromFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)869 Handle<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
GetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function)885 static 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
SetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function,Handle<Object> value)895 static 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
FunctionGetPrototype(Handle<JSFunction> function)919 Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
920 return GetFunctionPrototype(function->GetIsolate(), function);
921 }
922
923
FunctionSetPrototype(Handle<JSFunction> function,Handle<Object> prototype)924 Handle<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
FunctionPrototypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)932 void 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
FunctionPrototypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)944 void 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
FunctionPrototypeInfo(Isolate * isolate,PropertyAttributes attributes)960 Handle<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
FunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)975 void 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
FunctionLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)1001 void 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
FunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)1010 Handle<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
FunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1025 void 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
FunctionNameSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)1037 void 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
FunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)1046 Handle<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
ArgumentsForInlinedFunction(JavaScriptFrame * frame,Handle<JSFunction> inlined_function,int inlined_frame_index)1061 static 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
FindFunctionInFrame(JavaScriptFrame * frame,Handle<JSFunction> function)1089 static 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
GetFunctionArguments(Isolate * isolate,Handle<JSFunction> function)1101 Handle<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
FunctionGetArguments(Handle<JSFunction> function)1157 Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
1158 return GetFunctionArguments(function->GetIsolate(), function);
1159 }
1160
1161
FunctionArgumentsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1162 void 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
FunctionArgumentsSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)1174 void 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
FunctionArgumentsInfo(Isolate * isolate,PropertyAttributes attributes)1183 Handle<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
AllowAccessToFunction(Context * current_context,JSFunction * function)1198 static inline bool AllowAccessToFunction(Context* current_context,
1199 JSFunction* function) {
1200 return current_context->HasSameSecurityTokenAs(function->context());
1201 }
1202
1203
1204 class FrameFunctionIterator {
1205 public:
FrameFunctionIterator(Isolate * isolate,const DisallowHeapAllocation & promise)1206 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
1207 : isolate_(isolate),
1208 frame_iterator_(isolate),
1209 functions_(2),
1210 index_(0) {
1211 GetFunctions();
1212 }
next()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.
Find(JSFunction * function)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:
GetFunctions()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
FindCaller(Isolate * isolate,Handle<JSFunction> function)1256 MaybeHandle<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
FunctionCallerGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1305 void 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
FunctionCallerSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)1325 void 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
FunctionCallerInfo(Isolate * isolate,PropertyAttributes attributes)1334 Handle<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
ModuleGetExport(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)1348 static 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
ModuleSetExport(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)1375 static 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
MakeModuleExport(Handle<String> name,int index,PropertyAttributes attributes)1402 Handle<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