blob: 011372cbff7f237ed06d526369fffb04a4e0e1cb [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#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"
Steve Blocka7e24c12009-10-30 11:49:00 +000019
20namespace v8 {
21namespace internal {
22
23
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024Handle<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;
Steve Blocka7e24c12009-10-30 11:49:00 +000041}
42
43
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044Handle<ExecutableAccessorInfo> Accessors::CloneAccessor(
45 Isolate* isolate,
46 Handle<ExecutableAccessorInfo> accessor) {
47 Factory* factory = isolate->factory();
48 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
49 info->set_name(accessor->name());
50 info->set_flag(accessor->flag());
51 info->set_expected_receiver_type(accessor->expected_receiver_type());
52 info->set_getter(accessor->getter());
53 info->set_setter(accessor->setter());
54 info->set_data(accessor->data());
55 return info;
56}
57
58
59template <class C>
60static C* FindInstanceOf(Isolate* isolate, Object* obj) {
61 for (PrototypeIterator iter(isolate, obj,
62 PrototypeIterator::START_AT_RECEIVER);
63 !iter.IsAtEnd(); iter.Advance()) {
64 if (Is<C>(iter.GetCurrent())) return C::cast(iter.GetCurrent());
65 }
Steve Blocka7e24c12009-10-30 11:49:00 +000066 return NULL;
67}
68
69
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070static 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;
Steve Blocka7e24c12009-10-30 11:49:00 +000079}
80
81
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082// Returns true for properties that are accessors to object fields.
83// If true, *object_offset contains offset of object field.
84template <class T>
85bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
86 Handle<Name> name,
87 int* object_offset) {
88 Isolate* isolate = name->GetIsolate();
89
90 if (type->Is(T::String())) {
91 return CheckForName(name, isolate->factory()->length_string(),
92 String::kLengthOffset, object_offset);
93 }
94
95 if (!type->IsClass()) return false;
96 Handle<Map> map = type->AsClass()->Map();
97
98 switch (map->instance_type()) {
99 case JS_ARRAY_TYPE:
100 return
101 CheckForName(name, isolate->factory()->length_string(),
102 JSArray::kLengthOffset, object_offset);
103 case JS_TYPED_ARRAY_TYPE:
104 return
105 CheckForName(name, isolate->factory()->length_string(),
106 JSTypedArray::kLengthOffset, object_offset) ||
107 CheckForName(name, isolate->factory()->byte_length_string(),
108 JSTypedArray::kByteLengthOffset, object_offset) ||
109 CheckForName(name, isolate->factory()->byte_offset_string(),
110 JSTypedArray::kByteOffsetOffset, object_offset);
111 case JS_ARRAY_BUFFER_TYPE:
112 return
113 CheckForName(name, isolate->factory()->byte_length_string(),
114 JSArrayBuffer::kByteLengthOffset, object_offset);
115 case JS_DATA_VIEW_TYPE:
116 return
117 CheckForName(name, isolate->factory()->byte_length_string(),
118 JSDataView::kByteLengthOffset, object_offset) ||
119 CheckForName(name, isolate->factory()->byte_offset_string(),
120 JSDataView::kByteOffsetOffset, object_offset);
121 default:
122 return false;
123 }
124}
125
126
127template
128bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
129 Handle<Name> name,
130 int* object_offset);
131
132
133template
134bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
135 Handle<Name> name,
136 int* object_offset);
137
138
139bool SetPropertyOnInstanceIfInherited(
140 Isolate* isolate, const v8::PropertyCallbackInfo<void>& info,
141 v8::Local<v8::Name> name, Handle<Object> value) {
142 Handle<Object> holder = Utils::OpenHandle(*info.Holder());
143 Handle<Object> receiver = Utils::OpenHandle(*info.This());
144 if (*holder == *receiver) return false;
145 if (receiver->IsJSObject()) {
146 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
147 // This behaves sloppy since we lost the actual strict-mode.
148 // TODO(verwaest): Fix by making ExecutableAccessorInfo behave like data
149 // properties.
150 if (!object->map()->is_extensible()) return true;
151 JSObject::SetOwnPropertyIgnoreAttributes(object, Utils::OpenHandle(*name),
152 value, NONE).Check();
153 }
154 return true;
155}
156
157
158//
159// Accessors::ArgumentsIterator
160//
161
162
163void Accessors::ArgumentsIteratorGetter(
164 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
165 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
166 DisallowHeapAllocation no_allocation;
167 HandleScope scope(isolate);
168 Object* result = isolate->native_context()->array_values_iterator();
169 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
170}
171
172
173void Accessors::ArgumentsIteratorSetter(
174 v8::Local<v8::Name> name, v8::Local<v8::Value> val,
175 const v8::PropertyCallbackInfo<void>& info) {
176 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
177 HandleScope scope(isolate);
178 Handle<JSObject> object = Utils::OpenHandle(*info.This());
179 Handle<Object> value = Utils::OpenHandle(*val);
180
181 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) return;
182
183 LookupIterator it(object, Utils::OpenHandle(*name));
184 CHECK_EQ(LookupIterator::ACCESSOR, it.state());
185 DCHECK(it.HolderIsReceiverOrHiddenPrototype());
186 Object::SetDataProperty(&it, value);
187}
188
189
190Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
191 Isolate* isolate, PropertyAttributes attributes) {
192 Handle<Name> name(isolate->native_context()->iterator_symbol(), isolate);
193 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter,
194 &ArgumentsIteratorSetter, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000195}
196
197
198//
199// Accessors::ArrayLength
200//
201
202
Steve Blocka7e24c12009-10-30 11:49:00 +0000203// The helper function will 'flatten' Number objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
205 Handle<Object> value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 if (value->IsNumber() || !value->IsJSValue()) return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
208 DCHECK(wrapper->GetIsolate()->native_context()->number_function()->
Steve Block44f0eee2011-05-26 01:26:41 +0100209 has_initial_map());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 if (wrapper->map() == isolate->number_function()->initial_map()) {
211 return handle(wrapper->value(), isolate);
212 }
213
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 return value;
215}
216
217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218void 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;
Steve Block44f0eee2011-05-26 01:26:41 +0100223 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
225 Object* result = holder->length();
226 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000227}
228
229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230void Accessors::ArrayLengthSetter(
231 v8::Local<v8::Name> name,
232 v8::Local<v8::Value> val,
233 const v8::PropertyCallbackInfo<void>& info) {
234 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
235 HandleScope scope(isolate);
236 Handle<JSObject> object = Utils::OpenHandle(*info.This());
237 Handle<Object> value = Utils::OpenHandle(*val);
238 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
239 return;
240 }
241
242 value = FlattenNumber(isolate, value);
243
244 Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
245 MaybeHandle<Object> maybe;
246 Handle<Object> uint32_v;
247 maybe = Execution::ToUint32(isolate, value);
248 if (!maybe.ToHandle(&uint32_v)) {
249 isolate->OptionalRescheduleException(false);
250 return;
251 }
252 Handle<Object> number_v;
253 maybe = Execution::ToNumber(isolate, value);
254 if (!maybe.ToHandle(&number_v)) {
255 isolate->OptionalRescheduleException(false);
256 return;
257 }
258
259 if (uint32_v->Number() == number_v->Number()) {
260 maybe = JSArray::SetElementsLength(array_handle, uint32_v);
261 maybe.Check();
262 return;
263 }
264
265 Handle<Object> exception;
266 maybe = isolate->factory()->NewRangeError("invalid_array_length",
267 HandleVector<Object>(NULL, 0));
268 if (!maybe.ToHandle(&exception)) {
269 isolate->OptionalRescheduleException(false);
270 return;
271 }
272
273 isolate->ScheduleThrow(*exception);
274}
275
276
277Handle<AccessorInfo> Accessors::ArrayLengthInfo(
278 Isolate* isolate, PropertyAttributes attributes) {
279 return MakeAccessor(isolate,
280 isolate->factory()->length_string(),
281 &ArrayLengthGetter,
282 &ArrayLengthSetter,
283 attributes);
284}
285
Steve Blocka7e24c12009-10-30 11:49:00 +0000286
287
288//
289// Accessors::StringLength
290//
291
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292void 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);
Steve Blocka7e24c12009-10-30 11:49:00 +0000298
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 // 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)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000312}
313
314
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315void Accessors::StringLengthSetter(
316 v8::Local<v8::Name> name,
317 v8::Local<v8::Value> value,
318 const v8::PropertyCallbackInfo<void>& info) {
319 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000320}
321
322
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323Handle<AccessorInfo> Accessors::StringLengthInfo(
324 Isolate* isolate, PropertyAttributes attributes) {
325 return MakeAccessor(isolate,
326 isolate->factory()->length_string(),
327 &StringLengthGetter,
328 &StringLengthSetter,
329 attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000330}
331
332
Steve Blocka7e24c12009-10-30 11:49:00 +0000333//
334// Accessors::ScriptColumnOffset
335//
336
337
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338void 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)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000347}
348
349
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350void Accessors::ScriptColumnOffsetSetter(
351 v8::Local<v8::Name> name,
352 v8::Local<v8::Value> value,
353 const v8::PropertyCallbackInfo<void>& info) {
354 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000355}
356
357
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
359 Isolate* isolate, PropertyAttributes attributes) {
360 Handle<String> name(isolate->factory()->InternalizeOneByteString(
361 STATIC_CHAR_VECTOR("column_offset")));
362 return MakeAccessor(isolate,
363 name,
364 &ScriptColumnOffsetGetter,
365 &ScriptColumnOffsetSetter,
366 attributes);
367}
368
369
370//
371// Accessors::ScriptId
372//
373
374
375void Accessors::ScriptIdGetter(
376 v8::Local<v8::Name> name,
377 const v8::PropertyCallbackInfo<v8::Value>& info) {
378 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
379 DisallowHeapAllocation no_allocation;
380 HandleScope scope(isolate);
381 Object* object = *Utils::OpenHandle(*info.This());
382 Object* id = Script::cast(JSValue::cast(object)->value())->id();
383 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
384}
385
386
387void Accessors::ScriptIdSetter(
388 v8::Local<v8::Name> name,
389 v8::Local<v8::Value> value,
390 const v8::PropertyCallbackInfo<void>& info) {
391 UNREACHABLE();
392}
393
394
395Handle<AccessorInfo> Accessors::ScriptIdInfo(
396 Isolate* isolate, PropertyAttributes attributes) {
397 Handle<String> name(
398 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
399 return MakeAccessor(isolate,
400 name,
401 &ScriptIdGetter,
402 &ScriptIdSetter,
403 attributes);
404}
405
406
407//
408// Accessors::ScriptName
409//
410
411
412void Accessors::ScriptNameGetter(
413 v8::Local<v8::Name> name,
414 const v8::PropertyCallbackInfo<v8::Value>& info) {
415 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
416 DisallowHeapAllocation no_allocation;
417 HandleScope scope(isolate);
418 Object* object = *Utils::OpenHandle(*info.This());
419 Object* source = Script::cast(JSValue::cast(object)->value())->name();
420 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
421}
422
423
424void Accessors::ScriptNameSetter(
425 v8::Local<v8::Name> name,
426 v8::Local<v8::Value> value,
427 const v8::PropertyCallbackInfo<void>& info) {
428 UNREACHABLE();
429}
430
431
432Handle<AccessorInfo> Accessors::ScriptNameInfo(
433 Isolate* isolate, PropertyAttributes attributes) {
434 return MakeAccessor(isolate,
435 isolate->factory()->name_string(),
436 &ScriptNameGetter,
437 &ScriptNameSetter,
438 attributes);
439}
440
441
442//
443// Accessors::ScriptSource
444//
445
446
447void Accessors::ScriptSourceGetter(
448 v8::Local<v8::Name> name,
449 const v8::PropertyCallbackInfo<v8::Value>& info) {
450 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
451 DisallowHeapAllocation no_allocation;
452 HandleScope scope(isolate);
453 Object* object = *Utils::OpenHandle(*info.This());
454 Object* source = Script::cast(JSValue::cast(object)->value())->source();
455 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
456}
457
458
459void Accessors::ScriptSourceSetter(
460 v8::Local<v8::Name> name,
461 v8::Local<v8::Value> value,
462 const v8::PropertyCallbackInfo<void>& info) {
463 UNREACHABLE();
464}
465
466
467Handle<AccessorInfo> Accessors::ScriptSourceInfo(
468 Isolate* isolate, PropertyAttributes attributes) {
469 return MakeAccessor(isolate,
470 isolate->factory()->source_string(),
471 &ScriptSourceGetter,
472 &ScriptSourceSetter,
473 attributes);
474}
475
476
477//
478// Accessors::ScriptLineOffset
479//
480
481
482void Accessors::ScriptLineOffsetGetter(
483 v8::Local<v8::Name> name,
484 const v8::PropertyCallbackInfo<v8::Value>& info) {
485 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
486 DisallowHeapAllocation no_allocation;
487 HandleScope scope(isolate);
488 Object* object = *Utils::OpenHandle(*info.This());
489 Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
490 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
491}
492
493
494void Accessors::ScriptLineOffsetSetter(
495 v8::Local<v8::Name> name,
496 v8::Local<v8::Value> value,
497 const v8::PropertyCallbackInfo<void>& info) {
498 UNREACHABLE();
499}
500
501
502Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
503 Isolate* isolate, PropertyAttributes attributes) {
504 Handle<String> name(isolate->factory()->InternalizeOneByteString(
505 STATIC_CHAR_VECTOR("line_offset")));
506 return MakeAccessor(isolate,
507 name,
508 &ScriptLineOffsetGetter,
509 &ScriptLineOffsetSetter,
510 attributes);
511}
Steve Blocka7e24c12009-10-30 11:49:00 +0000512
513
514//
515// Accessors::ScriptType
516//
517
518
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519void 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)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000528}
529
530
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531void Accessors::ScriptTypeSetter(
532 v8::Local<v8::Name> name,
533 v8::Local<v8::Value> value,
534 const v8::PropertyCallbackInfo<void>& info) {
535 UNREACHABLE();
536}
537
538
539Handle<AccessorInfo> Accessors::ScriptTypeInfo(
540 Isolate* isolate, PropertyAttributes attributes) {
541 Handle<String> name(
542 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
543 return MakeAccessor(isolate,
544 name,
545 &ScriptTypeGetter,
546 &ScriptTypeSetter,
547 attributes);
548}
Steve Blocka7e24c12009-10-30 11:49:00 +0000549
550
551//
552// Accessors::ScriptCompilationType
553//
554
555
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556void 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)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000566}
567
568
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569void Accessors::ScriptCompilationTypeSetter(
570 v8::Local<v8::Name> name,
571 v8::Local<v8::Value> value,
572 const v8::PropertyCallbackInfo<void>& info) {
573 UNREACHABLE();
574}
575
576
577Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
578 Isolate* isolate, PropertyAttributes attributes) {
579 Handle<String> name(isolate->factory()->InternalizeOneByteString(
580 STATIC_CHAR_VECTOR("compilation_type")));
581 return MakeAccessor(isolate,
582 name,
583 &ScriptCompilationTypeGetter,
584 &ScriptCompilationTypeSetter,
585 attributes);
586}
Steve Blocka7e24c12009-10-30 11:49:00 +0000587
588
589//
590// Accessors::ScriptGetLineEnds
591//
592
593
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594void 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());
Steve Block44f0eee2011-05-26 01:26:41 +0100598 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 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());
Steve Blockd0582a62009-12-15 09:54:21 +0000604 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800605 // We do not want anyone to modify this array from JS.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
Steve Block44f0eee2011-05-26 01:26:41 +0100607 line_ends->map() == isolate->heap()->fixed_cow_array_map());
608 Handle<JSArray> js_array =
609 isolate->factory()->NewJSArrayWithElements(line_ends);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 info.GetReturnValue().Set(Utils::ToLocal(js_array));
Steve Blocka7e24c12009-10-30 11:49:00 +0000611}
612
613
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614void Accessors::ScriptLineEndsSetter(
615 v8::Local<v8::Name> name,
616 v8::Local<v8::Value> value,
617 const v8::PropertyCallbackInfo<void>& info) {
618 UNREACHABLE();
619}
620
621
622Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
623 Isolate* isolate, PropertyAttributes attributes) {
624 Handle<String> name(isolate->factory()->InternalizeOneByteString(
625 STATIC_CHAR_VECTOR("line_ends")));
626 return MakeAccessor(isolate,
627 name,
628 &ScriptLineEndsGetter,
629 &ScriptLineEndsSetter,
630 attributes);
631}
632
633
634//
635// Accessors::ScriptSourceUrl
636//
637
638
639void Accessors::ScriptSourceUrlGetter(
640 v8::Local<v8::Name> name,
641 const v8::PropertyCallbackInfo<v8::Value>& info) {
642 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
643 DisallowHeapAllocation no_allocation;
644 HandleScope scope(isolate);
645 Object* object = *Utils::OpenHandle(*info.This());
646 Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
647 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
648}
649
650
651void Accessors::ScriptSourceUrlSetter(
652 v8::Local<v8::Name> name,
653 v8::Local<v8::Value> value,
654 const v8::PropertyCallbackInfo<void>& info) {
655 UNREACHABLE();
656}
657
658
659Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
660 Isolate* isolate, PropertyAttributes attributes) {
661 return MakeAccessor(isolate,
662 isolate->factory()->source_url_string(),
663 &ScriptSourceUrlGetter,
664 &ScriptSourceUrlSetter,
665 attributes);
666}
667
668
669//
670// Accessors::ScriptSourceMappingUrl
671//
672
673
674void Accessors::ScriptSourceMappingUrlGetter(
675 v8::Local<v8::Name> name,
676 const v8::PropertyCallbackInfo<v8::Value>& info) {
677 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
678 DisallowHeapAllocation no_allocation;
679 HandleScope scope(isolate);
680 Object* object = *Utils::OpenHandle(*info.This());
681 Object* url =
682 Script::cast(JSValue::cast(object)->value())->source_mapping_url();
683 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
684}
685
686
687void Accessors::ScriptSourceMappingUrlSetter(
688 v8::Local<v8::Name> name,
689 v8::Local<v8::Value> value,
690 const v8::PropertyCallbackInfo<void>& info) {
691 UNREACHABLE();
692}
693
694
695Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
696 Isolate* isolate, PropertyAttributes attributes) {
697 return MakeAccessor(isolate,
698 isolate->factory()->source_mapping_url_string(),
699 &ScriptSourceMappingUrlGetter,
700 &ScriptSourceMappingUrlSetter,
701 attributes);
702}
Steve Blocka7e24c12009-10-30 11:49:00 +0000703
704
705//
706// Accessors::ScriptGetContextData
707//
708
709
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710void 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)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000719}
720
721
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722void Accessors::ScriptContextDataSetter(
723 v8::Local<v8::Name> name,
724 v8::Local<v8::Value> value,
725 const v8::PropertyCallbackInfo<void>& info) {
726 UNREACHABLE();
727}
728
729
730Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
731 Isolate* isolate, PropertyAttributes attributes) {
732 Handle<String> name(isolate->factory()->InternalizeOneByteString(
733 STATIC_CHAR_VECTOR("context_data")));
734 return MakeAccessor(isolate,
735 name,
736 &ScriptContextDataGetter,
737 &ScriptContextDataSetter,
738 attributes);
739}
Steve Blocka7e24c12009-10-30 11:49:00 +0000740
741
742//
Steve Blockd0582a62009-12-15 09:54:21 +0000743// Accessors::ScriptGetEvalFromScript
Steve Blocka7e24c12009-10-30 11:49:00 +0000744//
745
746
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747void 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()) {
Steve Blockd0582a62009-12-15 09:54:21 +0000757 Handle<SharedFunctionInfo> eval_from_shared(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000758 SharedFunctionInfo::cast(script->eval_from_shared()));
Steve Blockd0582a62009-12-15 09:54:21 +0000759 if (eval_from_shared->script()->IsScript()) {
760 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 result = Script::GetWrapper(eval_from_script);
Steve Blockd0582a62009-12-15 09:54:21 +0000762 }
763 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764
765 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000766}
767
768
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769void Accessors::ScriptEvalFromScriptSetter(
770 v8::Local<v8::Name> name,
771 v8::Local<v8::Value> value,
772 const v8::PropertyCallbackInfo<void>& info) {
773 UNREACHABLE();
774}
775
776
777Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
778 Isolate* isolate, PropertyAttributes attributes) {
779 Handle<String> name(isolate->factory()->InternalizeOneByteString(
780 STATIC_CHAR_VECTOR("eval_from_script")));
781 return MakeAccessor(isolate,
782 name,
783 &ScriptEvalFromScriptGetter,
784 &ScriptEvalFromScriptSetter,
785 attributes);
786}
Steve Blocka7e24c12009-10-30 11:49:00 +0000787
788
789//
Steve Blockd0582a62009-12-15 09:54:21 +0000790// Accessors::ScriptGetEvalFromScriptPosition
Steve Blocka7e24c12009-10-30 11:49:00 +0000791//
792
793
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794void 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);
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000812}
813
814
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815void Accessors::ScriptEvalFromScriptPositionSetter(
816 v8::Local<v8::Name> name,
817 v8::Local<v8::Value> value,
818 const v8::PropertyCallbackInfo<void>& info) {
819 UNREACHABLE();
820}
821
822
823Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
824 Isolate* isolate, PropertyAttributes attributes) {
825 Handle<String> name(isolate->factory()->InternalizeOneByteString(
826 STATIC_CHAR_VECTOR("eval_from_script_position")));
827 return MakeAccessor(isolate,
828 name,
829 &ScriptEvalFromScriptPositionGetter,
830 &ScriptEvalFromScriptPositionSetter,
831 attributes);
832}
Steve Blockd0582a62009-12-15 09:54:21 +0000833
834
835//
836// Accessors::ScriptGetEvalFromFunctionName
837//
838
839
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840void 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()));
Steve Blockd0582a62009-12-15 09:54:21 +0000851 // Find the name of the function calling eval.
852 if (!shared->name()->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 result = Handle<Object>(shared->name(), isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000854 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 result = Handle<Object>(shared->inferred_name(), isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000856 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blockd0582a62009-12-15 09:54:21 +0000858}
859
860
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861void Accessors::ScriptEvalFromFunctionNameSetter(
862 v8::Local<v8::Name> name,
863 v8::Local<v8::Value> value,
864 const v8::PropertyCallbackInfo<void>& info) {
865 UNREACHABLE();
866}
867
868
869Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
870 Isolate* isolate, PropertyAttributes attributes) {
871 Handle<String> name(isolate->factory()->InternalizeOneByteString(
872 STATIC_CHAR_VECTOR("eval_from_function_name")));
873 return MakeAccessor(isolate,
874 name,
875 &ScriptEvalFromFunctionNameGetter,
876 &ScriptEvalFromFunctionNameSetter,
877 attributes);
878}
Steve Blocka7e24c12009-10-30 11:49:00 +0000879
880
881//
882// Accessors::FunctionPrototype
883//
884
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885static Handle<Object> GetFunctionPrototype(Isolate* isolate,
886 Handle<JSFunction> function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 if (!function->has_prototype()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
889 JSFunction::SetPrototype(function, proto);
Steve Blocka7e24c12009-10-30 11:49:00 +0000890 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 return Handle<Object>(function->prototype(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000892}
893
894
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895static 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);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100905 }
906
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 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);
John Reck59135872010-11-02 12:39:01 -0700913 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914
Steve Blocka7e24c12009-10-30 11:49:00 +0000915 return function;
916}
917
918
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
920 return GetFunctionPrototype(function->GetIsolate(), function);
921}
922
923
924Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
925 Handle<Object> prototype) {
926 DCHECK(function->should_have_prototype());
927 Isolate* isolate = function->GetIsolate();
928 return SetFunctionPrototype(isolate, function, prototype);
929}
930
931
932void Accessors::FunctionPrototypeGetter(
933 v8::Local<v8::Name> name,
934 const v8::PropertyCallbackInfo<v8::Value>& info) {
935 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
936 HandleScope scope(isolate);
937 Handle<JSFunction> function =
938 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
939 Handle<Object> result = GetFunctionPrototype(isolate, function);
940 info.GetReturnValue().Set(Utils::ToLocal(result));
941}
942
943
944void Accessors::FunctionPrototypeSetter(
945 v8::Local<v8::Name> name,
946 v8::Local<v8::Value> val,
947 const v8::PropertyCallbackInfo<void>& info) {
948 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
949 HandleScope scope(isolate);
950 Handle<Object> value = Utils::OpenHandle(*val);
951 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
952 return;
953 }
954 Handle<JSFunction> object =
955 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
956 SetFunctionPrototype(isolate, object, value);
957}
958
959
960Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
961 Isolate* isolate, PropertyAttributes attributes) {
962 return MakeAccessor(isolate,
963 isolate->factory()->prototype_string(),
964 &FunctionPrototypeGetter,
965 &FunctionPrototypeSetter,
966 attributes);
967}
Steve Blocka7e24c12009-10-30 11:49:00 +0000968
969
970//
971// Accessors::FunctionLength
972//
973
974
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975void 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 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000987 // If the function isn't compiled yet, the length is not computed
988 // correctly yet. Compile it now and return the right length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000989 if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
990 length = function->shared()->length();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100991 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 if (isolate->has_pending_exception()) {
993 isolate->OptionalRescheduleException(false);
994 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000995 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 Handle<Object> result(Smi::FromInt(length), isolate);
997 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000998}
999
1000
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001001void Accessors::FunctionLengthSetter(
1002 v8::Local<v8::Name> name,
1003 v8::Local<v8::Value> val,
1004 const v8::PropertyCallbackInfo<void>& info) {
1005 // Function length is non writable, non configurable.
1006 UNREACHABLE();
1007}
1008
1009
1010Handle<AccessorInfo> Accessors::FunctionLengthInfo(
1011 Isolate* isolate, PropertyAttributes attributes) {
1012 return MakeAccessor(isolate,
1013 isolate->factory()->length_string(),
1014 &FunctionLengthGetter,
1015 &FunctionLengthSetter,
1016 attributes);
1017}
Steve Blocka7e24c12009-10-30 11:49:00 +00001018
1019
1020//
1021// Accessors::FunctionName
1022//
1023
1024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025void 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));
Steve Blocka7e24c12009-10-30 11:49:00 +00001034}
1035
1036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037void Accessors::FunctionNameSetter(
1038 v8::Local<v8::Name> name,
1039 v8::Local<v8::Value> val,
1040 const v8::PropertyCallbackInfo<void>& info) {
1041 // Function name is non writable, non configurable.
1042 UNREACHABLE();
1043}
1044
1045
1046Handle<AccessorInfo> Accessors::FunctionNameInfo(
1047 Isolate* isolate, PropertyAttributes attributes) {
1048 return MakeAccessor(isolate,
1049 isolate->factory()->name_string(),
1050 &FunctionNameGetter,
1051 &FunctionNameSetter,
1052 attributes);
1053}
Steve Blocka7e24c12009-10-30 11:49:00 +00001054
1055
1056//
1057// Accessors::FunctionArguments
1058//
1059
Ben Murdochb0fe1622011-05-05 13:52:32 +01001060
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001061static Handle<Object> ArgumentsForInlinedFunction(
Ben Murdochb0fe1622011-05-05 13:52:32 +01001062 JavaScriptFrame* frame,
1063 Handle<JSFunction> inlined_function,
1064 int inlined_frame_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 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();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001073 Handle<JSObject> arguments =
Steve Block44f0eee2011-05-26 01:26:41 +01001074 factory->NewArgumentsObject(inlined_function, args_count);
1075 Handle<FixedArray> array = factory->NewFixedArray(args_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076 slot_refs.Prepare(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001077 for (int i = 0; i < args_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078 Handle<Object> value = slot_refs.GetNext(isolate, 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001079 array->set(i, *value);
1080 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001081 slot_refs.Finish(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082 arguments->set_elements(*array);
1083
1084 // Return the freshly allocated arguments object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 return arguments;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001086}
1087
Steve Blocka7e24c12009-10-30 11:49:00 +00001088
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001089static int FindFunctionInFrame(JavaScriptFrame* frame,
1090 Handle<JSFunction> function) {
1091 DisallowHeapAllocation no_allocation;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001092 List<JSFunction*> functions(2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 frame->GetFunctions(&functions);
1094 for (int i = functions.length() - 1; i >= 0; i--) {
1095 if (functions[i] == *function) return i;
1096 }
1097 return -1;
1098}
1099
1100
1101Handle<Object> GetFunctionArguments(Isolate* isolate,
1102 Handle<JSFunction> function) {
1103 if (function->shared()->native()) return isolate->factory()->null_value();
1104
1105 // Find the top invocation of the function by traversing frames.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001106 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 JavaScriptFrame* frame = it.frame();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108 int function_index = FindFunctionInFrame(frame, function);
1109 if (function_index < 0) continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001110
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 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);
Steve Blocka7e24c12009-10-30 11:49:00 +00001117 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118
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;
Steve Blocka7e24c12009-10-30 11:49:00 +00001150 }
1151
1152 // No frame corresponding to the given function found. Return null.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 return isolate->factory()->null_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001154}
1155
1156
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
1158 return GetFunctionArguments(function->GetIsolate(), function);
1159}
1160
1161
1162void Accessors::FunctionArgumentsGetter(
1163 v8::Local<v8::Name> name,
1164 const v8::PropertyCallbackInfo<v8::Value>& info) {
1165 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1166 HandleScope scope(isolate);
1167 Handle<JSFunction> function =
1168 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1169 Handle<Object> result = GetFunctionArguments(isolate, function);
1170 info.GetReturnValue().Set(Utils::ToLocal(result));
1171}
1172
1173
1174void Accessors::FunctionArgumentsSetter(
1175 v8::Local<v8::Name> name,
1176 v8::Local<v8::Value> val,
1177 const v8::PropertyCallbackInfo<void>& info) {
1178 // Function arguments is non writable, non configurable.
1179 UNREACHABLE();
1180}
1181
1182
1183Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
1184 Isolate* isolate, PropertyAttributes attributes) {
1185 return MakeAccessor(isolate,
1186 isolate->factory()->arguments_string(),
1187 &FunctionArgumentsGetter,
1188 &FunctionArgumentsSetter,
1189 attributes);
1190}
Steve Blocka7e24c12009-10-30 11:49:00 +00001191
1192
1193//
1194// Accessors::FunctionCaller
1195//
1196
1197
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001198static inline bool AllowAccessToFunction(Context* current_context,
1199 JSFunction* function) {
1200 return current_context->HasSameSecurityTokenAs(function->context());
Steve Block44f0eee2011-05-26 01:26:41 +01001201}
1202
1203
Ben Murdoch257744e2011-11-30 15:57:28 +00001204class FrameFunctionIterator {
1205 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
1207 : isolate_(isolate),
1208 frame_iterator_(isolate),
Ben Murdoch257744e2011-11-30 15:57:28 +00001209 functions_(2),
1210 index_(0) {
1211 GetFunctions();
1212 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001213 JSFunction* next() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 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;
Ben Murdoch257744e2011-11-30 15:57:28 +00001224 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001225 }
1226
1227 // Iterate through functions until the first occurence of 'function'.
1228 // Returns true if 'function' is found, and false if the iterator ends
1229 // without finding it.
1230 bool Find(JSFunction* function) {
1231 JSFunction* next_function;
1232 do {
1233 next_function = next();
1234 if (next_function == function) return true;
1235 } while (next_function != NULL);
1236 return false;
1237 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001238
Ben Murdoch257744e2011-11-30 15:57:28 +00001239 private:
1240 void GetFunctions() {
1241 functions_.Rewind(0);
1242 if (frame_iterator_.done()) return;
1243 JavaScriptFrame* frame = frame_iterator_.frame();
1244 frame->GetFunctions(&functions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001245 DCHECK(functions_.length() > 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001246 frame_iterator_.Advance();
1247 index_ = functions_.length() - 1;
1248 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249 Isolate* isolate_;
Ben Murdoch257744e2011-11-30 15:57:28 +00001250 JavaScriptFrameIterator frame_iterator_;
1251 List<JSFunction*> functions_;
1252 int index_;
1253};
1254
1255
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256MaybeHandle<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 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001263 // Find the function from the frames.
1264 if (!it.Find(*function)) {
1265 // No frame corresponding to the given function found. Return null.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 return MaybeHandle<JSFunction>();
Steve Blocka7e24c12009-10-30 11:49:00 +00001267 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001268 // Find previously called non-toplevel function.
1269 JSFunction* caller;
1270 do {
1271 caller = it.next();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 if (caller == NULL) return MaybeHandle<JSFunction>();
Ben Murdoch257744e2011-11-30 15:57:28 +00001273 } 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 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 if (!caller->shared()->native() && potential_caller != NULL) {
1283 caller = potential_caller;
1284 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001285 // 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()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 return MaybeHandle<JSFunction>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001290 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 // 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);
Steve Blocka7e24c12009-10-30 11:49:00 +00001302}
1303
1304
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305void Accessors::FunctionCallerGetter(
1306 v8::Local<v8::Name> name,
1307 const v8::PropertyCallbackInfo<v8::Value>& info) {
1308 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1309 HandleScope scope(isolate);
1310 Handle<JSFunction> function =
1311 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1312 Handle<Object> result;
1313 MaybeHandle<JSFunction> maybe_caller;
1314 maybe_caller = FindCaller(isolate, function);
1315 Handle<JSFunction> caller;
1316 if (maybe_caller.ToHandle(&caller)) {
1317 result = caller;
1318 } else {
1319 result = isolate->factory()->null_value();
1320 }
1321 info.GetReturnValue().Set(Utils::ToLocal(result));
1322}
1323
1324
1325void Accessors::FunctionCallerSetter(
1326 v8::Local<v8::Name> name,
1327 v8::Local<v8::Value> val,
1328 const v8::PropertyCallbackInfo<void>& info) {
1329 // Function caller is non writable, non configurable.
1330 UNREACHABLE();
1331}
1332
1333
1334Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1335 Isolate* isolate, PropertyAttributes attributes) {
1336 return MakeAccessor(isolate,
1337 isolate->factory()->caller_string(),
1338 &FunctionCallerGetter,
1339 &FunctionCallerSetter,
1340 attributes);
1341}
Steve Blocka7e24c12009-10-30 11:49:00 +00001342
1343
1344//
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345// Accessors::MakeModuleExport
Steve Blocka7e24c12009-10-30 11:49:00 +00001346//
1347
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348static 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);
Steve Blocka7e24c12009-10-30 11:49:00 +00001359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 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;
Steve Blocka7e24c12009-10-30 11:49:00 +00001370 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001372}
1373
1374
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001375static 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));
Steve Blocka7e24c12009-10-30 11:49:00 +00001399}
1400
1401
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402Handle<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
Steve Blocka7e24c12009-10-30 11:49:00 +00001421
1422} } // namespace v8::internal