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<AccessorInfo> info = factory->NewAccessorInfo();
31 info->set_property_attributes(attributes);
32 info->set_all_can_read(false);
33 info->set_all_can_write(false);
34 info->set_is_special_data_property(true);
35 info->set_is_sloppy(false);
36 name = factory->InternalizeName(name);
37 info->set_name(*name);
38 Handle<Object> get = v8::FromCData(isolate, getter);
39 if (setter == nullptr) setter = &ReconfigureToDataProperty;
40 Handle<Object> set = v8::FromCData(isolate, setter);
41 info->set_getter(*get);
42 info->set_setter(*set);
43 Address redirected = info->redirected_getter();
44 if (redirected != nullptr) {
45 Handle<Object> js_get = v8::FromCData(isolate, redirected);
46 info->set_js_getter(*js_get);
47 }
48 return info;
49 }
50
51
CheckForName(Handle<Name> name,Handle<String> property_name,int offset,int * object_offset)52 static V8_INLINE bool CheckForName(Handle<Name> name,
53 Handle<String> property_name,
54 int offset,
55 int* object_offset) {
56 if (Name::Equals(name, property_name)) {
57 *object_offset = offset;
58 return true;
59 }
60 return false;
61 }
62
63
64 // Returns true for properties that are accessors to object fields.
65 // If true, *object_offset contains offset of object field.
IsJSObjectFieldAccessor(Handle<Map> map,Handle<Name> name,int * object_offset)66 bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
67 int* object_offset) {
68 Isolate* isolate = name->GetIsolate();
69
70 switch (map->instance_type()) {
71 case JS_ARRAY_TYPE:
72 return
73 CheckForName(name, isolate->factory()->length_string(),
74 JSArray::kLengthOffset, object_offset);
75 case JS_ARRAY_BUFFER_TYPE:
76 return CheckForName(name, isolate->factory()->byte_length_string(),
77 JSArrayBuffer::kByteLengthOffset, object_offset);
78 default:
79 if (map->instance_type() < FIRST_NONSTRING_TYPE) {
80 return CheckForName(name, isolate->factory()->length_string(),
81 String::kLengthOffset, object_offset);
82 }
83
84 return false;
85 }
86 }
87
88
89 namespace {
90
ReplaceAccessorWithDataProperty(Isolate * isolate,Handle<Object> receiver,Handle<JSObject> holder,Handle<Name> name,Handle<Object> value)91 MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty(
92 Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
93 Handle<Name> name, Handle<Object> value) {
94 LookupIterator it(receiver, name, holder,
95 LookupIterator::OWN_SKIP_INTERCEPTOR);
96 // Skip any access checks we might hit. This accessor should never hit in a
97 // situation where the caller does not have access.
98 if (it.state() == LookupIterator::ACCESS_CHECK) {
99 CHECK(it.HasAccess());
100 it.Next();
101 }
102 DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
103 CHECK_EQ(LookupIterator::ACCESSOR, it.state());
104 it.ReconfigureDataProperty(value, it.property_attributes());
105 return value;
106 }
107
108 } // namespace
109
ReconfigureToDataProperty(v8::Local<v8::Name> key,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)110 void Accessors::ReconfigureToDataProperty(
111 v8::Local<v8::Name> key, v8::Local<v8::Value> val,
112 const v8::PropertyCallbackInfo<void>& info) {
113 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
114 HandleScope scope(isolate);
115 Handle<Object> receiver = Utils::OpenHandle(*info.This());
116 Handle<JSObject> holder =
117 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
118 Handle<Name> name = Utils::OpenHandle(*key);
119 Handle<Object> value = Utils::OpenHandle(*val);
120 MaybeHandle<Object> result =
121 ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
122 if (result.is_null()) isolate->OptionalRescheduleException(false);
123 }
124
125 //
126 // Accessors::ArgumentsIterator
127 //
128
129
ArgumentsIteratorGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)130 void Accessors::ArgumentsIteratorGetter(
131 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
132 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
133 DisallowHeapAllocation no_allocation;
134 HandleScope scope(isolate);
135 Object* result = isolate->native_context()->array_values_iterator();
136 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
137 }
138
139
ArgumentsIteratorInfo(Isolate * isolate,PropertyAttributes attributes)140 Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
141 Isolate* isolate, PropertyAttributes attributes) {
142 Handle<Name> name = isolate->factory()->iterator_symbol();
143 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr,
144 attributes);
145 }
146
147
148 //
149 // Accessors::ArrayLength
150 //
151
152
ArrayLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)153 void Accessors::ArrayLengthGetter(
154 v8::Local<v8::Name> name,
155 const v8::PropertyCallbackInfo<v8::Value>& info) {
156 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
157 DisallowHeapAllocation no_allocation;
158 HandleScope scope(isolate);
159 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
160 Object* result = holder->length();
161 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
162 }
163
164
ArrayLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)165 void Accessors::ArrayLengthSetter(
166 v8::Local<v8::Name> name,
167 v8::Local<v8::Value> val,
168 const v8::PropertyCallbackInfo<void>& info) {
169 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
170 HandleScope scope(isolate);
171
172 Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
173 Handle<JSArray> array = Handle<JSArray>::cast(object);
174 Handle<Object> length_obj = Utils::OpenHandle(*val);
175
176 uint32_t length = 0;
177 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
178 isolate->OptionalRescheduleException(false);
179 return;
180 }
181
182 JSArray::SetLength(array, length);
183
184 if (info.ShouldThrowOnError()) {
185 uint32_t actual_new_len = 0;
186 CHECK(array->length()->ToArrayLength(&actual_new_len));
187 // Throw TypeError if there were non-deletable elements.
188 if (actual_new_len != length) {
189 Factory* factory = isolate->factory();
190 isolate->Throw(*factory->NewTypeError(
191 MessageTemplate::kStrictDeleteProperty,
192 factory->NewNumberFromUint(actual_new_len - 1), array));
193 isolate->OptionalRescheduleException(false);
194 }
195 }
196 }
197
198
ArrayLengthInfo(Isolate * isolate,PropertyAttributes attributes)199 Handle<AccessorInfo> Accessors::ArrayLengthInfo(
200 Isolate* isolate, PropertyAttributes attributes) {
201 return MakeAccessor(isolate,
202 isolate->factory()->length_string(),
203 &ArrayLengthGetter,
204 &ArrayLengthSetter,
205 attributes);
206 }
207
208
209 //
210 // Accessors::StringLength
211 //
212
StringLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)213 void Accessors::StringLengthGetter(
214 v8::Local<v8::Name> name,
215 const v8::PropertyCallbackInfo<v8::Value>& info) {
216 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
217 DisallowHeapAllocation no_allocation;
218 HandleScope scope(isolate);
219
220 // We have a slight impedance mismatch between the external API and the way we
221 // use callbacks internally: Externally, callbacks can only be used with
222 // v8::Object, but internally we have callbacks on entities which are higher
223 // in the hierarchy, in this case for String values.
224
225 Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
226 if (!value->IsString()) {
227 // Not a string value. That means that we either got a String wrapper or
228 // a Value with a String wrapper in its prototype chain.
229 value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
230 }
231 Object* result = Smi::FromInt(String::cast(value)->length());
232 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
233 }
234
235
StringLengthInfo(Isolate * isolate,PropertyAttributes attributes)236 Handle<AccessorInfo> Accessors::StringLengthInfo(
237 Isolate* isolate, PropertyAttributes attributes) {
238 return MakeAccessor(isolate, isolate->factory()->length_string(),
239 &StringLengthGetter, nullptr, attributes);
240 }
241
242
243 //
244 // Accessors::ScriptColumnOffset
245 //
246
247
ScriptColumnOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)248 void Accessors::ScriptColumnOffsetGetter(
249 v8::Local<v8::Name> name,
250 const v8::PropertyCallbackInfo<v8::Value>& info) {
251 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
252 DisallowHeapAllocation no_allocation;
253 HandleScope scope(isolate);
254 Object* object = *Utils::OpenHandle(*info.Holder());
255 Object* res = Smi::FromInt(
256 Script::cast(JSValue::cast(object)->value())->column_offset());
257 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
258 }
259
260
ScriptColumnOffsetInfo(Isolate * isolate,PropertyAttributes attributes)261 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
262 Isolate* isolate, PropertyAttributes attributes) {
263 Handle<String> name(isolate->factory()->InternalizeOneByteString(
264 STATIC_CHAR_VECTOR("column_offset")));
265 return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr,
266 attributes);
267 }
268
269
270 //
271 // Accessors::ScriptId
272 //
273
274
ScriptIdGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)275 void Accessors::ScriptIdGetter(
276 v8::Local<v8::Name> name,
277 const v8::PropertyCallbackInfo<v8::Value>& info) {
278 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
279 DisallowHeapAllocation no_allocation;
280 HandleScope scope(isolate);
281 Object* object = *Utils::OpenHandle(*info.Holder());
282 Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id());
283 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
284 }
285
286
ScriptIdInfo(Isolate * isolate,PropertyAttributes attributes)287 Handle<AccessorInfo> Accessors::ScriptIdInfo(
288 Isolate* isolate, PropertyAttributes attributes) {
289 Handle<String> name(
290 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
291 return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes);
292 }
293
294
295 //
296 // Accessors::ScriptName
297 //
298
299
ScriptNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)300 void Accessors::ScriptNameGetter(
301 v8::Local<v8::Name> name,
302 const v8::PropertyCallbackInfo<v8::Value>& info) {
303 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
304 DisallowHeapAllocation no_allocation;
305 HandleScope scope(isolate);
306 Object* object = *Utils::OpenHandle(*info.Holder());
307 Object* source = Script::cast(JSValue::cast(object)->value())->name();
308 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
309 }
310
311
ScriptNameInfo(Isolate * isolate,PropertyAttributes attributes)312 Handle<AccessorInfo> Accessors::ScriptNameInfo(
313 Isolate* isolate, PropertyAttributes attributes) {
314 return MakeAccessor(isolate, isolate->factory()->name_string(),
315 &ScriptNameGetter, nullptr, attributes);
316 }
317
318
319 //
320 // Accessors::ScriptSource
321 //
322
323
ScriptSourceGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)324 void Accessors::ScriptSourceGetter(
325 v8::Local<v8::Name> name,
326 const v8::PropertyCallbackInfo<v8::Value>& info) {
327 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
328 DisallowHeapAllocation no_allocation;
329 HandleScope scope(isolate);
330 Object* object = *Utils::OpenHandle(*info.Holder());
331 Object* source = Script::cast(JSValue::cast(object)->value())->source();
332 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
333 }
334
335
ScriptSourceInfo(Isolate * isolate,PropertyAttributes attributes)336 Handle<AccessorInfo> Accessors::ScriptSourceInfo(
337 Isolate* isolate, PropertyAttributes attributes) {
338 return MakeAccessor(isolate, isolate->factory()->source_string(),
339 &ScriptSourceGetter, nullptr, attributes);
340 }
341
342
343 //
344 // Accessors::ScriptLineOffset
345 //
346
347
ScriptLineOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)348 void Accessors::ScriptLineOffsetGetter(
349 v8::Local<v8::Name> name,
350 const v8::PropertyCallbackInfo<v8::Value>& info) {
351 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
352 DisallowHeapAllocation no_allocation;
353 HandleScope scope(isolate);
354 Object* object = *Utils::OpenHandle(*info.Holder());
355 Object* res =
356 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset());
357 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
358 }
359
360
ScriptLineOffsetInfo(Isolate * isolate,PropertyAttributes attributes)361 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
362 Isolate* isolate, PropertyAttributes attributes) {
363 Handle<String> name(isolate->factory()->InternalizeOneByteString(
364 STATIC_CHAR_VECTOR("line_offset")));
365 return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr,
366 attributes);
367 }
368
369
370 //
371 // Accessors::ScriptType
372 //
373
374
ScriptTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)375 void Accessors::ScriptTypeGetter(
376 v8::Local<v8::Name> name,
377 const v8::PropertyCallbackInfo<v8::Value>& info) {
378 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
379 DisallowHeapAllocation no_allocation;
380 HandleScope scope(isolate);
381 Object* object = *Utils::OpenHandle(*info.Holder());
382 Object* res =
383 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type());
384 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
385 }
386
387
ScriptTypeInfo(Isolate * isolate,PropertyAttributes attributes)388 Handle<AccessorInfo> Accessors::ScriptTypeInfo(
389 Isolate* isolate, PropertyAttributes attributes) {
390 Handle<String> name(
391 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
392 return MakeAccessor(isolate, name, &ScriptTypeGetter, nullptr, attributes);
393 }
394
395
396 //
397 // Accessors::ScriptCompilationType
398 //
399
400
ScriptCompilationTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)401 void Accessors::ScriptCompilationTypeGetter(
402 v8::Local<v8::Name> name,
403 const v8::PropertyCallbackInfo<v8::Value>& info) {
404 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
405 DisallowHeapAllocation no_allocation;
406 HandleScope scope(isolate);
407 Object* object = *Utils::OpenHandle(*info.Holder());
408 Object* res = Smi::FromInt(
409 Script::cast(JSValue::cast(object)->value())->compilation_type());
410 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
411 }
412
413
ScriptCompilationTypeInfo(Isolate * isolate,PropertyAttributes attributes)414 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
415 Isolate* isolate, PropertyAttributes attributes) {
416 Handle<String> name(isolate->factory()->InternalizeOneByteString(
417 STATIC_CHAR_VECTOR("compilation_type")));
418 return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr,
419 attributes);
420 }
421
422
423 //
424 // Accessors::ScriptGetLineEnds
425 //
426
427
ScriptLineEndsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)428 void Accessors::ScriptLineEndsGetter(
429 v8::Local<v8::Name> name,
430 const v8::PropertyCallbackInfo<v8::Value>& info) {
431 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
432 HandleScope scope(isolate);
433 Handle<Object> object = Utils::OpenHandle(*info.Holder());
434 Handle<Script> script(
435 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
436 Script::InitLineEnds(script);
437 DCHECK(script->line_ends()->IsFixedArray());
438 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
439 // We do not want anyone to modify this array from JS.
440 DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
441 line_ends->map() == isolate->heap()->fixed_cow_array_map());
442 Handle<JSArray> js_array =
443 isolate->factory()->NewJSArrayWithElements(line_ends);
444 info.GetReturnValue().Set(Utils::ToLocal(js_array));
445 }
446
447
ScriptLineEndsInfo(Isolate * isolate,PropertyAttributes attributes)448 Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
449 Isolate* isolate, PropertyAttributes attributes) {
450 Handle<String> name(isolate->factory()->InternalizeOneByteString(
451 STATIC_CHAR_VECTOR("line_ends")));
452 return MakeAccessor(isolate, name, &ScriptLineEndsGetter, nullptr,
453 attributes);
454 }
455
456
457 //
458 // Accessors::ScriptSourceUrl
459 //
460
461
ScriptSourceUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)462 void Accessors::ScriptSourceUrlGetter(
463 v8::Local<v8::Name> name,
464 const v8::PropertyCallbackInfo<v8::Value>& info) {
465 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
466 DisallowHeapAllocation no_allocation;
467 HandleScope scope(isolate);
468 Object* object = *Utils::OpenHandle(*info.Holder());
469 Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
470 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
471 }
472
473
ScriptSourceUrlInfo(Isolate * isolate,PropertyAttributes attributes)474 Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
475 Isolate* isolate, PropertyAttributes attributes) {
476 return MakeAccessor(isolate, isolate->factory()->source_url_string(),
477 &ScriptSourceUrlGetter, nullptr, attributes);
478 }
479
480
481 //
482 // Accessors::ScriptSourceMappingUrl
483 //
484
485
ScriptSourceMappingUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)486 void Accessors::ScriptSourceMappingUrlGetter(
487 v8::Local<v8::Name> name,
488 const v8::PropertyCallbackInfo<v8::Value>& info) {
489 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
490 DisallowHeapAllocation no_allocation;
491 HandleScope scope(isolate);
492 Object* object = *Utils::OpenHandle(*info.Holder());
493 Object* url =
494 Script::cast(JSValue::cast(object)->value())->source_mapping_url();
495 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
496 }
497
498
ScriptSourceMappingUrlInfo(Isolate * isolate,PropertyAttributes attributes)499 Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
500 Isolate* isolate, PropertyAttributes attributes) {
501 return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(),
502 &ScriptSourceMappingUrlGetter, nullptr, attributes);
503 }
504
505
506 //
507 // Accessors::ScriptIsEmbedderDebugScript
508 //
509
510
ScriptIsEmbedderDebugScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)511 void Accessors::ScriptIsEmbedderDebugScriptGetter(
512 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
513 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
514 DisallowHeapAllocation no_allocation;
515 HandleScope scope(isolate);
516 Object* object = *Utils::OpenHandle(*info.Holder());
517 bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
518 ->origin_options()
519 .IsEmbedderDebugScript();
520 Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script);
521 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
522 }
523
524
ScriptIsEmbedderDebugScriptInfo(Isolate * isolate,PropertyAttributes attributes)525 Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo(
526 Isolate* isolate, PropertyAttributes attributes) {
527 Handle<String> name(isolate->factory()->InternalizeOneByteString(
528 STATIC_CHAR_VECTOR("is_debugger_script")));
529 return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter,
530 nullptr, attributes);
531 }
532
533
534 //
535 // Accessors::ScriptGetContextData
536 //
537
538
ScriptContextDataGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)539 void Accessors::ScriptContextDataGetter(
540 v8::Local<v8::Name> name,
541 const v8::PropertyCallbackInfo<v8::Value>& info) {
542 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
543 DisallowHeapAllocation no_allocation;
544 HandleScope scope(isolate);
545 Object* object = *Utils::OpenHandle(*info.Holder());
546 Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
547 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
548 }
549
550
ScriptContextDataInfo(Isolate * isolate,PropertyAttributes attributes)551 Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
552 Isolate* isolate, PropertyAttributes attributes) {
553 Handle<String> name(isolate->factory()->InternalizeOneByteString(
554 STATIC_CHAR_VECTOR("context_data")));
555 return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr,
556 attributes);
557 }
558
559
560 //
561 // Accessors::ScriptGetEvalFromScript
562 //
563
564
ScriptEvalFromScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)565 void Accessors::ScriptEvalFromScriptGetter(
566 v8::Local<v8::Name> name,
567 const v8::PropertyCallbackInfo<v8::Value>& info) {
568 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
569 HandleScope scope(isolate);
570 Handle<Object> object = Utils::OpenHandle(*info.Holder());
571 Handle<Script> script(
572 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
573 Handle<Object> result = isolate->factory()->undefined_value();
574 if (!script->eval_from_shared()->IsUndefined(isolate)) {
575 Handle<SharedFunctionInfo> eval_from_shared(
576 SharedFunctionInfo::cast(script->eval_from_shared()));
577 if (eval_from_shared->script()->IsScript()) {
578 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
579 result = Script::GetWrapper(eval_from_script);
580 }
581 }
582
583 info.GetReturnValue().Set(Utils::ToLocal(result));
584 }
585
586
ScriptEvalFromScriptInfo(Isolate * isolate,PropertyAttributes attributes)587 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
588 Isolate* isolate, PropertyAttributes attributes) {
589 Handle<String> name(isolate->factory()->InternalizeOneByteString(
590 STATIC_CHAR_VECTOR("eval_from_script")));
591 return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr,
592 attributes);
593 }
594
595
596 //
597 // Accessors::ScriptGetEvalFromScriptPosition
598 //
599
600
ScriptEvalFromScriptPositionGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)601 void Accessors::ScriptEvalFromScriptPositionGetter(
602 v8::Local<v8::Name> name,
603 const v8::PropertyCallbackInfo<v8::Value>& info) {
604 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
605 HandleScope scope(isolate);
606 Handle<Object> object = Utils::OpenHandle(*info.Holder());
607 Handle<Script> script(
608 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
609 Handle<Object> result = isolate->factory()->undefined_value();
610 if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
611 result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate);
612 }
613 info.GetReturnValue().Set(Utils::ToLocal(result));
614 }
615
616
ScriptEvalFromScriptPositionInfo(Isolate * isolate,PropertyAttributes attributes)617 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
618 Isolate* isolate, PropertyAttributes attributes) {
619 Handle<String> name(isolate->factory()->InternalizeOneByteString(
620 STATIC_CHAR_VECTOR("eval_from_script_position")));
621 return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter,
622 nullptr, attributes);
623 }
624
625
626 //
627 // Accessors::ScriptGetEvalFromFunctionName
628 //
629
630
ScriptEvalFromFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)631 void Accessors::ScriptEvalFromFunctionNameGetter(
632 v8::Local<v8::Name> name,
633 const v8::PropertyCallbackInfo<v8::Value>& info) {
634 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
635 HandleScope scope(isolate);
636 Handle<Object> object = Utils::OpenHandle(*info.Holder());
637 Handle<Script> script(
638 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
639 Handle<Object> result = isolate->factory()->undefined_value();
640 if (!script->eval_from_shared()->IsUndefined(isolate)) {
641 Handle<SharedFunctionInfo> shared(
642 SharedFunctionInfo::cast(script->eval_from_shared()));
643 // Find the name of the function calling eval.
644 if (!shared->name()->IsUndefined(isolate)) {
645 result = Handle<Object>(shared->name(), isolate);
646 } else {
647 result = Handle<Object>(shared->inferred_name(), isolate);
648 }
649 }
650 info.GetReturnValue().Set(Utils::ToLocal(result));
651 }
652
653
ScriptEvalFromFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)654 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
655 Isolate* isolate, PropertyAttributes attributes) {
656 Handle<String> name(isolate->factory()->InternalizeOneByteString(
657 STATIC_CHAR_VECTOR("eval_from_function_name")));
658 return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr,
659 attributes);
660 }
661
662
663 //
664 // Accessors::FunctionPrototype
665 //
666
GetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function)667 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
668 Handle<JSFunction> function) {
669 if (!function->has_prototype()) {
670 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
671 JSFunction::SetPrototype(function, proto);
672 }
673 return Handle<Object>(function->prototype(), isolate);
674 }
675
676
SetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function,Handle<Object> value)677 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
678 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
679 JSFunction::SetPrototype(function, value);
680 DCHECK(function->prototype() == *value);
681 return function;
682 }
683
684
FunctionSetPrototype(Handle<JSFunction> function,Handle<Object> prototype)685 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
686 Handle<Object> prototype) {
687 DCHECK(function->IsConstructor());
688 Isolate* isolate = function->GetIsolate();
689 return SetFunctionPrototype(isolate, function, prototype);
690 }
691
692
FunctionPrototypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)693 void Accessors::FunctionPrototypeGetter(
694 v8::Local<v8::Name> name,
695 const v8::PropertyCallbackInfo<v8::Value>& info) {
696 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
697 HandleScope scope(isolate);
698 Handle<JSFunction> function =
699 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
700 Handle<Object> result = GetFunctionPrototype(isolate, function);
701 info.GetReturnValue().Set(Utils::ToLocal(result));
702 }
703
704
FunctionPrototypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<void> & info)705 void Accessors::FunctionPrototypeSetter(
706 v8::Local<v8::Name> name,
707 v8::Local<v8::Value> val,
708 const v8::PropertyCallbackInfo<void>& info) {
709 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
710 HandleScope scope(isolate);
711 Handle<Object> value = Utils::OpenHandle(*val);
712 Handle<JSFunction> object =
713 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
714 if (SetFunctionPrototype(isolate, object, value).is_null()) {
715 isolate->OptionalRescheduleException(false);
716 }
717 }
718
719
FunctionPrototypeInfo(Isolate * isolate,PropertyAttributes attributes)720 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
721 Isolate* isolate, PropertyAttributes attributes) {
722 return MakeAccessor(isolate,
723 isolate->factory()->prototype_string(),
724 &FunctionPrototypeGetter,
725 &FunctionPrototypeSetter,
726 attributes);
727 }
728
729
730 //
731 // Accessors::FunctionLength
732 //
733
734
FunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)735 void Accessors::FunctionLengthGetter(
736 v8::Local<v8::Name> name,
737 const v8::PropertyCallbackInfo<v8::Value>& info) {
738 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
739 HandleScope scope(isolate);
740 Handle<JSFunction> function =
741 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
742 Handle<Object> result;
743 if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) {
744 result = handle(Smi::FromInt(0), isolate);
745 isolate->OptionalRescheduleException(false);
746 }
747
748 info.GetReturnValue().Set(Utils::ToLocal(result));
749 }
750
FunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)751 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
752 Isolate* isolate, PropertyAttributes attributes) {
753 return MakeAccessor(isolate, isolate->factory()->length_string(),
754 &FunctionLengthGetter, &ReconfigureToDataProperty,
755 attributes);
756 }
757
758
759 //
760 // Accessors::FunctionName
761 //
762
763
FunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)764 void Accessors::FunctionNameGetter(
765 v8::Local<v8::Name> name,
766 const v8::PropertyCallbackInfo<v8::Value>& info) {
767 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
768 HandleScope scope(isolate);
769 Handle<JSFunction> function =
770 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
771 Handle<Object> result = JSFunction::GetName(isolate, function);
772 info.GetReturnValue().Set(Utils::ToLocal(result));
773 }
774
FunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)775 Handle<AccessorInfo> Accessors::FunctionNameInfo(
776 Isolate* isolate, PropertyAttributes attributes) {
777 return MakeAccessor(isolate, isolate->factory()->name_string(),
778 &FunctionNameGetter, &ReconfigureToDataProperty,
779 attributes);
780 }
781
782
783 //
784 // Accessors::FunctionArguments
785 //
786
787
ArgumentsForInlinedFunction(JavaScriptFrame * frame,Handle<JSFunction> inlined_function,int inlined_frame_index)788 static Handle<Object> ArgumentsForInlinedFunction(
789 JavaScriptFrame* frame,
790 Handle<JSFunction> inlined_function,
791 int inlined_frame_index) {
792 Isolate* isolate = inlined_function->GetIsolate();
793 Factory* factory = isolate->factory();
794
795 TranslatedState translated_values(frame);
796 translated_values.Prepare(false, frame->fp());
797
798 int argument_count = 0;
799 TranslatedFrame* translated_frame =
800 translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
801 &argument_count);
802 TranslatedFrame::iterator iter = translated_frame->begin();
803
804 // Skip the function.
805 iter++;
806
807 // Skip the receiver.
808 iter++;
809 argument_count--;
810
811 Handle<JSObject> arguments =
812 factory->NewArgumentsObject(inlined_function, argument_count);
813 Handle<FixedArray> array = factory->NewFixedArray(argument_count);
814 bool should_deoptimize = false;
815 for (int i = 0; i < argument_count; ++i) {
816 // If we materialize any object, we should deopt because we might alias
817 // an object that was eliminated by escape analysis.
818 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
819 Handle<Object> value = iter->GetValue();
820 array->set(i, *value);
821 iter++;
822 }
823 arguments->set_elements(*array);
824
825 if (should_deoptimize) {
826 translated_values.StoreMaterializedValuesAndDeopt();
827 }
828
829 // Return the freshly allocated arguments object.
830 return arguments;
831 }
832
833
FindFunctionInFrame(JavaScriptFrame * frame,Handle<JSFunction> function)834 static int FindFunctionInFrame(JavaScriptFrame* frame,
835 Handle<JSFunction> function) {
836 DisallowHeapAllocation no_allocation;
837 List<JSFunction*> functions(2);
838 frame->GetFunctions(&functions);
839 for (int i = functions.length() - 1; i >= 0; i--) {
840 if (functions[i] == *function) return i;
841 }
842 return -1;
843 }
844
845
846 namespace {
847
GetFunctionArguments(Isolate * isolate,Handle<JSFunction> function)848 Handle<Object> GetFunctionArguments(Isolate* isolate,
849 Handle<JSFunction> function) {
850 // Find the top invocation of the function by traversing frames.
851 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
852 JavaScriptFrame* frame = it.frame();
853 int function_index = FindFunctionInFrame(frame, function);
854 if (function_index < 0) continue;
855
856 if (function_index > 0) {
857 // The function in question was inlined. Inlined functions have the
858 // correct number of arguments and no allocated arguments object, so
859 // we can construct a fresh one by interpreting the function's
860 // deoptimization input data.
861 return ArgumentsForInlinedFunction(frame, function, function_index);
862 }
863
864 // Find the frame that holds the actual arguments passed to the function.
865 it.AdvanceToArgumentsFrame();
866 frame = it.frame();
867
868 // Get the number of arguments and construct an arguments object
869 // mirror for the right frame.
870 const int length = frame->ComputeParametersCount();
871 Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
872 function, length);
873 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
874
875 // Copy the parameters to the arguments object.
876 DCHECK(array->length() == length);
877 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
878 arguments->set_elements(*array);
879
880 // Return the freshly allocated arguments object.
881 return arguments;
882 }
883
884 // No frame corresponding to the given function found. Return null.
885 return isolate->factory()->null_value();
886 }
887
888 } // namespace
889
890
FunctionGetArguments(Handle<JSFunction> function)891 Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
892 Handle<Object> arguments =
893 GetFunctionArguments(function->GetIsolate(), function);
894 CHECK(arguments->IsJSObject());
895 return Handle<JSObject>::cast(arguments);
896 }
897
898
FunctionArgumentsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)899 void Accessors::FunctionArgumentsGetter(
900 v8::Local<v8::Name> name,
901 const v8::PropertyCallbackInfo<v8::Value>& info) {
902 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
903 HandleScope scope(isolate);
904 Handle<JSFunction> function =
905 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
906 Handle<Object> result =
907 function->shared()->native()
908 ? Handle<Object>::cast(isolate->factory()->null_value())
909 : GetFunctionArguments(isolate, function);
910 info.GetReturnValue().Set(Utils::ToLocal(result));
911 }
912
913
FunctionArgumentsInfo(Isolate * isolate,PropertyAttributes attributes)914 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
915 Isolate* isolate, PropertyAttributes attributes) {
916 return MakeAccessor(isolate, isolate->factory()->arguments_string(),
917 &FunctionArgumentsGetter, nullptr, attributes);
918 }
919
920
921 //
922 // Accessors::FunctionCaller
923 //
924
925
AllowAccessToFunction(Context * current_context,JSFunction * function)926 static inline bool AllowAccessToFunction(Context* current_context,
927 JSFunction* function) {
928 return current_context->HasSameSecurityTokenAs(function->context());
929 }
930
931
932 class FrameFunctionIterator {
933 public:
FrameFunctionIterator(Isolate * isolate,const DisallowHeapAllocation & promise)934 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
935 : isolate_(isolate),
936 frame_iterator_(isolate),
937 functions_(2),
938 index_(0) {
939 GetFunctions();
940 }
next()941 JSFunction* next() {
942 while (true) {
943 if (functions_.length() == 0) return NULL;
944 JSFunction* next_function = functions_[index_];
945 index_--;
946 if (index_ < 0) {
947 GetFunctions();
948 }
949 // Skip functions from other origins.
950 if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
951 return next_function;
952 }
953 }
954
955 // Iterate through functions until the first occurence of 'function'.
956 // Returns true if 'function' is found, and false if the iterator ends
957 // without finding it.
Find(JSFunction * function)958 bool Find(JSFunction* function) {
959 JSFunction* next_function;
960 do {
961 next_function = next();
962 if (next_function == function) return true;
963 } while (next_function != NULL);
964 return false;
965 }
966
967 private:
GetFunctions()968 void GetFunctions() {
969 functions_.Rewind(0);
970 if (frame_iterator_.done()) return;
971 JavaScriptFrame* frame = frame_iterator_.frame();
972 frame->GetFunctions(&functions_);
973 DCHECK(functions_.length() > 0);
974 frame_iterator_.Advance();
975 index_ = functions_.length() - 1;
976 }
977 Isolate* isolate_;
978 JavaScriptFrameIterator frame_iterator_;
979 List<JSFunction*> functions_;
980 int index_;
981 };
982
983
FindCaller(Isolate * isolate,Handle<JSFunction> function)984 MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
985 Handle<JSFunction> function) {
986 DisallowHeapAllocation no_allocation;
987 FrameFunctionIterator it(isolate, no_allocation);
988 if (function->shared()->native()) {
989 return MaybeHandle<JSFunction>();
990 }
991 // Find the function from the frames.
992 if (!it.Find(*function)) {
993 // No frame corresponding to the given function found. Return null.
994 return MaybeHandle<JSFunction>();
995 }
996 // Find previously called non-toplevel function.
997 JSFunction* caller;
998 do {
999 caller = it.next();
1000 if (caller == NULL) return MaybeHandle<JSFunction>();
1001 } while (caller->shared()->is_toplevel());
1002
1003 // If caller is a built-in function and caller's caller is also built-in,
1004 // use that instead.
1005 JSFunction* potential_caller = caller;
1006 while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) {
1007 caller = potential_caller;
1008 potential_caller = it.next();
1009 }
1010 if (!caller->shared()->native() && potential_caller != NULL) {
1011 caller = potential_caller;
1012 }
1013 // Censor if the caller is not a sloppy mode function.
1014 // Change from ES5, which used to throw, see:
1015 // https://bugs.ecmascript.org/show_bug.cgi?id=310
1016 if (is_strict(caller->shared()->language_mode())) {
1017 return MaybeHandle<JSFunction>();
1018 }
1019 // Don't return caller from another security context.
1020 if (!AllowAccessToFunction(isolate->context(), caller)) {
1021 return MaybeHandle<JSFunction>();
1022 }
1023 return Handle<JSFunction>(caller);
1024 }
1025
1026
FunctionCallerGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1027 void Accessors::FunctionCallerGetter(
1028 v8::Local<v8::Name> name,
1029 const v8::PropertyCallbackInfo<v8::Value>& info) {
1030 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1031 HandleScope scope(isolate);
1032 Handle<JSFunction> function =
1033 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1034 Handle<Object> result;
1035 MaybeHandle<JSFunction> maybe_caller;
1036 maybe_caller = FindCaller(isolate, function);
1037 Handle<JSFunction> caller;
1038 if (maybe_caller.ToHandle(&caller)) {
1039 result = caller;
1040 } else {
1041 result = isolate->factory()->null_value();
1042 }
1043 info.GetReturnValue().Set(Utils::ToLocal(result));
1044 }
1045
1046
FunctionCallerInfo(Isolate * isolate,PropertyAttributes attributes)1047 Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1048 Isolate* isolate, PropertyAttributes attributes) {
1049 return MakeAccessor(isolate, isolate->factory()->caller_string(),
1050 &FunctionCallerGetter, nullptr, attributes);
1051 }
1052
1053
1054 //
1055 // Accessors::BoundFunctionLength
1056 //
1057
BoundFunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1058 void Accessors::BoundFunctionLengthGetter(
1059 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1060 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1061 HandleScope scope(isolate);
1062 Handle<JSBoundFunction> function =
1063 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1064
1065 Handle<Smi> target_length;
1066 Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
1067 isolate);
1068 if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) {
1069 target_length = handle(Smi::FromInt(0), isolate);
1070 isolate->OptionalRescheduleException(false);
1071 return;
1072 }
1073
1074 int bound_length = function->bound_arguments()->length();
1075 int length = Max(0, target_length->value() - bound_length);
1076
1077 Handle<Object> result(Smi::FromInt(length), isolate);
1078 info.GetReturnValue().Set(Utils::ToLocal(result));
1079 }
1080
BoundFunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)1081 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
1082 Isolate* isolate, PropertyAttributes attributes) {
1083 return MakeAccessor(isolate, isolate->factory()->length_string(),
1084 &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
1085 attributes);
1086 }
1087
1088 //
1089 // Accessors::BoundFunctionName
1090 //
1091
BoundFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1092 void Accessors::BoundFunctionNameGetter(
1093 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1094 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1095 HandleScope scope(isolate);
1096 Handle<JSBoundFunction> function =
1097 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1098 Handle<Object> result;
1099 if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
1100 isolate->OptionalRescheduleException(false);
1101 return;
1102 }
1103 info.GetReturnValue().Set(Utils::ToLocal(result));
1104 }
1105
BoundFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)1106 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
1107 Isolate* isolate, PropertyAttributes attributes) {
1108 return MakeAccessor(isolate, isolate->factory()->name_string(),
1109 &BoundFunctionNameGetter, &ReconfigureToDataProperty,
1110 attributes);
1111 }
1112
1113 //
1114 // Accessors::MakeModuleExport
1115 //
1116
ModuleGetExport(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info)1117 static void ModuleGetExport(v8::Local<v8::Name> property,
1118 const v8::PropertyCallbackInfo<v8::Value>& info) {
1119 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1120 Context* context = Context::cast(instance->context());
1121 DCHECK(context->IsModuleContext());
1122 Isolate* isolate = instance->GetIsolate();
1123 int slot = info.Data()
1124 ->Int32Value(info.GetIsolate()->GetCurrentContext())
1125 .FromMaybe(-1);
1126 if (slot < 0 || slot >= context->length()) {
1127 Handle<Name> name = v8::Utils::OpenHandle(*property);
1128
1129 Handle<Object> exception = isolate->factory()->NewReferenceError(
1130 MessageTemplate::kNotDefined, name);
1131 isolate->ScheduleThrow(*exception);
1132 return;
1133 }
1134 Object* value = context->get(slot);
1135 if (value->IsTheHole(isolate)) {
1136 Handle<Name> name = v8::Utils::OpenHandle(*property);
1137
1138 Handle<Object> exception = isolate->factory()->NewReferenceError(
1139 MessageTemplate::kNotDefined, name);
1140 isolate->ScheduleThrow(*exception);
1141 return;
1142 }
1143 info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
1144 }
1145
1146
ModuleSetExport(v8::Local<v8::Name> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)1147 static void ModuleSetExport(v8::Local<v8::Name> property,
1148 v8::Local<v8::Value> value,
1149 const v8::PropertyCallbackInfo<void>& info) {
1150 if (!info.ShouldThrowOnError()) return;
1151 Handle<Name> name = v8::Utils::OpenHandle(*property);
1152 Isolate* isolate = name->GetIsolate();
1153 Handle<Object> exception =
1154 isolate->factory()->NewTypeError(MessageTemplate::kNotDefined, name);
1155 isolate->ScheduleThrow(*exception);
1156 }
1157
1158
MakeModuleExport(Handle<String> name,int index,PropertyAttributes attributes)1159 Handle<AccessorInfo> Accessors::MakeModuleExport(
1160 Handle<String> name,
1161 int index,
1162 PropertyAttributes attributes) {
1163 Isolate* isolate = name->GetIsolate();
1164 Handle<AccessorInfo> info = MakeAccessor(isolate, name, &ModuleGetExport,
1165 &ModuleSetExport, attributes);
1166 info->set_data(Smi::FromInt(index));
1167 return info;
1168 }
1169
1170
1171 } // namespace internal
1172 } // namespace v8
1173