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