blob: 662a9e126b04b1bad9489ddb468c09666436eff1 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/accessors.h"
8#include "src/api.h"
9#include "src/compiler.h"
10#include "src/contexts.h"
11#include "src/deoptimizer.h"
12#include "src/execution.h"
13#include "src/factory.h"
14#include "src/frames-inl.h"
15#include "src/isolate.h"
16#include "src/list-inl.h"
17#include "src/property-details.h"
18#include "src/prototype.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000019
20namespace v8 {
21namespace internal {
22
23
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024Handle<AccessorInfo> Accessors::MakeAccessor(
25 Isolate* isolate,
26 Handle<Name> name,
27 AccessorNameGetterCallback getter,
28 AccessorNameSetterCallback setter,
29 PropertyAttributes attributes) {
30 Factory* factory = isolate->factory();
31 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
32 info->set_property_attributes(attributes);
33 info->set_all_can_read(false);
34 info->set_all_can_write(false);
35 info->set_name(*name);
36 Handle<Object> get = v8::FromCData(isolate, getter);
37 Handle<Object> set = v8::FromCData(isolate, setter);
38 info->set_getter(*get);
39 info->set_setter(*set);
40 return info;
Steve Blocka7e24c12009-10-30 11:49:00 +000041}
42
43
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044Handle<ExecutableAccessorInfo> Accessors::CloneAccessor(
45 Isolate* isolate,
46 Handle<ExecutableAccessorInfo> accessor) {
47 Factory* factory = isolate->factory();
48 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
49 info->set_name(accessor->name());
50 info->set_flag(accessor->flag());
51 info->set_expected_receiver_type(accessor->expected_receiver_type());
52 info->set_getter(accessor->getter());
53 info->set_setter(accessor->setter());
54 info->set_data(accessor->data());
55 return info;
56}
57
58
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059static 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;
Steve Blocka7e24c12009-10-30 11:49:00 +000068}
69
70
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071// Returns true for properties that are accessors to object fields.
72// If true, *object_offset contains offset of object field.
73template <class T>
74bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
75 Handle<Name> name,
76 int* object_offset) {
77 Isolate* isolate = name->GetIsolate();
78
79 if (type->Is(T::String())) {
80 return CheckForName(name, isolate->factory()->length_string(),
81 String::kLengthOffset, object_offset);
82 }
83
84 if (!type->IsClass()) return false;
85 Handle<Map> map = type->AsClass()->Map();
86
87 switch (map->instance_type()) {
88 case JS_ARRAY_TYPE:
89 return
90 CheckForName(name, isolate->factory()->length_string(),
91 JSArray::kLengthOffset, object_offset);
92 case JS_TYPED_ARRAY_TYPE:
93 return
94 CheckForName(name, isolate->factory()->length_string(),
95 JSTypedArray::kLengthOffset, object_offset) ||
96 CheckForName(name, isolate->factory()->byte_length_string(),
97 JSTypedArray::kByteLengthOffset, object_offset) ||
98 CheckForName(name, isolate->factory()->byte_offset_string(),
99 JSTypedArray::kByteOffsetOffset, object_offset);
100 case JS_ARRAY_BUFFER_TYPE:
101 return
102 CheckForName(name, isolate->factory()->byte_length_string(),
103 JSArrayBuffer::kByteLengthOffset, object_offset);
104 case JS_DATA_VIEW_TYPE:
105 return
106 CheckForName(name, isolate->factory()->byte_length_string(),
107 JSDataView::kByteLengthOffset, object_offset) ||
108 CheckForName(name, isolate->factory()->byte_offset_string(),
109 JSDataView::kByteOffsetOffset, object_offset);
110 default:
111 return false;
112 }
113}
114
115
116template
117bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
118 Handle<Name> name,
119 int* object_offset);
120
121
122template
123bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
124 Handle<Name> name,
125 int* object_offset);
126
127
128bool SetPropertyOnInstanceIfInherited(
129 Isolate* isolate, const v8::PropertyCallbackInfo<void>& info,
130 v8::Local<v8::Name> name, Handle<Object> value) {
131 Handle<Object> holder = Utils::OpenHandle(*info.Holder());
132 Handle<Object> receiver = Utils::OpenHandle(*info.This());
133 if (*holder == *receiver) return false;
134 if (receiver->IsJSObject()) {
135 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
136 // This behaves sloppy since we lost the actual strict-mode.
137 // TODO(verwaest): Fix by making ExecutableAccessorInfo behave like data
138 // properties.
139 if (!object->map()->is_extensible()) return true;
140 JSObject::SetOwnPropertyIgnoreAttributes(object, Utils::OpenHandle(*name),
141 value, NONE).Check();
142 }
143 return true;
144}
145
146
147//
148// Accessors::ArgumentsIterator
149//
150
151
152void Accessors::ArgumentsIteratorGetter(
153 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
154 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
155 DisallowHeapAllocation no_allocation;
156 HandleScope scope(isolate);
157 Object* result = isolate->native_context()->array_values_iterator();
158 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
159}
160
161
162void Accessors::ArgumentsIteratorSetter(
163 v8::Local<v8::Name> name, v8::Local<v8::Value> val,
164 const v8::PropertyCallbackInfo<void>& info) {
165 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
166 HandleScope scope(isolate);
167 Handle<JSObject> object = Utils::OpenHandle(*info.This());
168 Handle<Object> value = Utils::OpenHandle(*val);
169
170 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) return;
171
172 LookupIterator it(object, Utils::OpenHandle(*name));
173 CHECK_EQ(LookupIterator::ACCESSOR, it.state());
174 DCHECK(it.HolderIsReceiverOrHiddenPrototype());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175
176 if (Object::SetDataProperty(&it, value).is_null()) {
177 isolate->OptionalRescheduleException(false);
178 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179}
180
181
182Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
183 Isolate* isolate, PropertyAttributes attributes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400184 Handle<Name> name = isolate->factory()->iterator_symbol();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter,
186 &ArgumentsIteratorSetter, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000187}
188
189
190//
191// Accessors::ArrayLength
192//
193
194
Steve Blocka7e24c12009-10-30 11:49:00 +0000195// The helper function will 'flatten' Number objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
197 Handle<Object> value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000198 if (value->IsNumber() || !value->IsJSValue()) return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
200 DCHECK(wrapper->GetIsolate()->native_context()->number_function()->
Steve Block44f0eee2011-05-26 01:26:41 +0100201 has_initial_map());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 if (wrapper->map() == isolate->number_function()->initial_map()) {
203 return handle(wrapper->value(), isolate);
204 }
205
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 return value;
207}
208
209
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210void Accessors::ArrayLengthGetter(
211 v8::Local<v8::Name> name,
212 const v8::PropertyCallbackInfo<v8::Value>& info) {
213 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
214 DisallowHeapAllocation no_allocation;
Steve Block44f0eee2011-05-26 01:26:41 +0100215 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
217 Object* result = holder->length();
218 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000219}
220
221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222void Accessors::ArrayLengthSetter(
223 v8::Local<v8::Name> name,
224 v8::Local<v8::Value> val,
225 const v8::PropertyCallbackInfo<void>& info) {
226 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
227 HandleScope scope(isolate);
228 Handle<JSObject> object = Utils::OpenHandle(*info.This());
229 Handle<Object> value = Utils::OpenHandle(*val);
230 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
231 return;
232 }
233
234 value = FlattenNumber(isolate, value);
235
236 Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
237 MaybeHandle<Object> maybe;
238 Handle<Object> uint32_v;
239 maybe = Execution::ToUint32(isolate, value);
240 if (!maybe.ToHandle(&uint32_v)) {
241 isolate->OptionalRescheduleException(false);
242 return;
243 }
244 Handle<Object> number_v;
245 maybe = Execution::ToNumber(isolate, value);
246 if (!maybe.ToHandle(&number_v)) {
247 isolate->OptionalRescheduleException(false);
248 return;
249 }
250
251 if (uint32_v->Number() == number_v->Number()) {
252 maybe = JSArray::SetElementsLength(array_handle, uint32_v);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253 if (maybe.is_null()) isolate->OptionalRescheduleException(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 return;
255 }
256
257 Handle<Object> exception;
258 maybe = isolate->factory()->NewRangeError("invalid_array_length",
259 HandleVector<Object>(NULL, 0));
260 if (!maybe.ToHandle(&exception)) {
261 isolate->OptionalRescheduleException(false);
262 return;
263 }
264
265 isolate->ScheduleThrow(*exception);
266}
267
268
269Handle<AccessorInfo> Accessors::ArrayLengthInfo(
270 Isolate* isolate, PropertyAttributes attributes) {
271 return MakeAccessor(isolate,
272 isolate->factory()->length_string(),
273 &ArrayLengthGetter,
274 &ArrayLengthSetter,
275 attributes);
276}
277
Steve Blocka7e24c12009-10-30 11:49:00 +0000278
279
280//
281// Accessors::StringLength
282//
283
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284void Accessors::StringLengthGetter(
285 v8::Local<v8::Name> name,
286 const v8::PropertyCallbackInfo<v8::Value>& info) {
287 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
288 DisallowHeapAllocation no_allocation;
289 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000290
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 // We have a slight impedance mismatch between the external API and the way we
292 // use callbacks internally: Externally, callbacks can only be used with
293 // v8::Object, but internally we have callbacks on entities which are higher
294 // in the hierarchy, in this case for String values.
295
296 Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
297 if (!value->IsString()) {
298 // Not a string value. That means that we either got a String wrapper or
299 // a Value with a String wrapper in its prototype chain.
300 value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
301 }
302 Object* result = Smi::FromInt(String::cast(value)->length());
303 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000304}
305
306
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307void Accessors::StringLengthSetter(
308 v8::Local<v8::Name> name,
309 v8::Local<v8::Value> value,
310 const v8::PropertyCallbackInfo<void>& info) {
311 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000312}
313
314
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315Handle<AccessorInfo> Accessors::StringLengthInfo(
316 Isolate* isolate, PropertyAttributes attributes) {
317 return MakeAccessor(isolate,
318 isolate->factory()->length_string(),
319 &StringLengthGetter,
320 &StringLengthSetter,
321 attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000322}
323
324
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325template <typename Char>
326inline int CountRequiredEscapes(Handle<String> source) {
327 DisallowHeapAllocation no_gc;
328 int escapes = 0;
329 Vector<const Char> src = source->GetCharVector<Char>();
330 for (int i = 0; i < src.length(); i++) {
331 if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++;
332 }
333 return escapes;
334}
335
336
337template <typename Char, typename StringType>
338inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
339 Handle<StringType> result) {
340 DisallowHeapAllocation no_gc;
341 Vector<const Char> src = source->GetCharVector<Char>();
342 Vector<Char> dst(result->GetChars(), result->length());
343 int s = 0;
344 int d = 0;
345 while (s < src.length()) {
346 if (src[s] == '/' && (s == 0 || src[s - 1] != '\\')) dst[d++] = '\\';
347 dst[d++] = src[s++];
348 }
349 DCHECK_EQ(result->length(), d);
350 return result;
351}
352
353
354MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
355 Handle<String> source) {
356 String::Flatten(source);
357 if (source->length() == 0) return isolate->factory()->query_colon_string();
358 bool one_byte = source->IsOneByteRepresentationUnderneath();
359 int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
360 : CountRequiredEscapes<uc16>(source);
361 if (escapes == 0) return source;
362 int length = source->length() + escapes;
363 if (one_byte) {
364 Handle<SeqOneByteString> result;
365 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
366 isolate->factory()->NewRawOneByteString(length),
367 String);
368 return WriteEscapedRegExpSource<uint8_t>(source, result);
369 } else {
370 Handle<SeqTwoByteString> result;
371 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
372 isolate->factory()->NewRawTwoByteString(length),
373 String);
374 return WriteEscapedRegExpSource<uc16>(source, result);
375 }
376}
377
378
379// Implements ECMA262 ES6 draft 21.2.5.9
380void Accessors::RegExpSourceGetter(
381 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
382 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
383 HandleScope scope(isolate);
384
385 Handle<Object> holder =
386 Utils::OpenHandle(*v8::Local<v8::Value>(info.Holder()));
387 Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(holder);
388 Handle<String> result;
389 if (regexp->TypeTag() == JSRegExp::NOT_COMPILED) {
390 result = isolate->factory()->empty_string();
391 } else {
392 Handle<String> pattern(regexp->Pattern(), isolate);
393 MaybeHandle<String> maybe = EscapeRegExpSource(isolate, pattern);
394 if (!maybe.ToHandle(&result)) {
395 isolate->OptionalRescheduleException(false);
396 return;
397 }
398 }
399 info.GetReturnValue().Set(Utils::ToLocal(result));
400}
401
402
403void Accessors::RegExpSourceSetter(v8::Local<v8::Name> name,
404 v8::Local<v8::Value> value,
405 const v8::PropertyCallbackInfo<void>& info) {
406 UNREACHABLE();
407}
408
409
410Handle<AccessorInfo> Accessors::RegExpSourceInfo(
411 Isolate* isolate, PropertyAttributes attributes) {
412 return MakeAccessor(isolate, isolate->factory()->source_string(),
413 &RegExpSourceGetter, &RegExpSourceSetter, attributes);
414}
415
416
Steve Blocka7e24c12009-10-30 11:49:00 +0000417//
418// Accessors::ScriptColumnOffset
419//
420
421
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422void Accessors::ScriptColumnOffsetGetter(
423 v8::Local<v8::Name> name,
424 const v8::PropertyCallbackInfo<v8::Value>& info) {
425 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
426 DisallowHeapAllocation no_allocation;
427 HandleScope scope(isolate);
428 Object* object = *Utils::OpenHandle(*info.This());
429 Object* res = Script::cast(JSValue::cast(object)->value())->column_offset();
430 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000431}
432
433
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434void Accessors::ScriptColumnOffsetSetter(
435 v8::Local<v8::Name> name,
436 v8::Local<v8::Value> value,
437 const v8::PropertyCallbackInfo<void>& info) {
438 UNREACHABLE();
Steve Blocka7e24c12009-10-30 11:49:00 +0000439}
440
441
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
443 Isolate* isolate, PropertyAttributes attributes) {
444 Handle<String> name(isolate->factory()->InternalizeOneByteString(
445 STATIC_CHAR_VECTOR("column_offset")));
446 return MakeAccessor(isolate,
447 name,
448 &ScriptColumnOffsetGetter,
449 &ScriptColumnOffsetSetter,
450 attributes);
451}
452
453
454//
455// Accessors::ScriptId
456//
457
458
459void Accessors::ScriptIdGetter(
460 v8::Local<v8::Name> name,
461 const v8::PropertyCallbackInfo<v8::Value>& info) {
462 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
463 DisallowHeapAllocation no_allocation;
464 HandleScope scope(isolate);
465 Object* object = *Utils::OpenHandle(*info.This());
466 Object* id = Script::cast(JSValue::cast(object)->value())->id();
467 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
468}
469
470
471void Accessors::ScriptIdSetter(
472 v8::Local<v8::Name> name,
473 v8::Local<v8::Value> value,
474 const v8::PropertyCallbackInfo<void>& info) {
475 UNREACHABLE();
476}
477
478
479Handle<AccessorInfo> Accessors::ScriptIdInfo(
480 Isolate* isolate, PropertyAttributes attributes) {
481 Handle<String> name(
482 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
483 return MakeAccessor(isolate,
484 name,
485 &ScriptIdGetter,
486 &ScriptIdSetter,
487 attributes);
488}
489
490
491//
492// Accessors::ScriptName
493//
494
495
496void Accessors::ScriptNameGetter(
497 v8::Local<v8::Name> name,
498 const v8::PropertyCallbackInfo<v8::Value>& info) {
499 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
500 DisallowHeapAllocation no_allocation;
501 HandleScope scope(isolate);
502 Object* object = *Utils::OpenHandle(*info.This());
503 Object* source = Script::cast(JSValue::cast(object)->value())->name();
504 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
505}
506
507
508void Accessors::ScriptNameSetter(
509 v8::Local<v8::Name> name,
510 v8::Local<v8::Value> value,
511 const v8::PropertyCallbackInfo<void>& info) {
512 UNREACHABLE();
513}
514
515
516Handle<AccessorInfo> Accessors::ScriptNameInfo(
517 Isolate* isolate, PropertyAttributes attributes) {
518 return MakeAccessor(isolate,
519 isolate->factory()->name_string(),
520 &ScriptNameGetter,
521 &ScriptNameSetter,
522 attributes);
523}
524
525
526//
527// Accessors::ScriptSource
528//
529
530
531void Accessors::ScriptSourceGetter(
532 v8::Local<v8::Name> name,
533 const v8::PropertyCallbackInfo<v8::Value>& info) {
534 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
535 DisallowHeapAllocation no_allocation;
536 HandleScope scope(isolate);
537 Object* object = *Utils::OpenHandle(*info.This());
538 Object* source = Script::cast(JSValue::cast(object)->value())->source();
539 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
540}
541
542
543void Accessors::ScriptSourceSetter(
544 v8::Local<v8::Name> name,
545 v8::Local<v8::Value> value,
546 const v8::PropertyCallbackInfo<void>& info) {
547 UNREACHABLE();
548}
549
550
551Handle<AccessorInfo> Accessors::ScriptSourceInfo(
552 Isolate* isolate, PropertyAttributes attributes) {
553 return MakeAccessor(isolate,
554 isolate->factory()->source_string(),
555 &ScriptSourceGetter,
556 &ScriptSourceSetter,
557 attributes);
558}
559
560
561//
562// Accessors::ScriptLineOffset
563//
564
565
566void Accessors::ScriptLineOffsetGetter(
567 v8::Local<v8::Name> name,
568 const v8::PropertyCallbackInfo<v8::Value>& info) {
569 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
570 DisallowHeapAllocation no_allocation;
571 HandleScope scope(isolate);
572 Object* object = *Utils::OpenHandle(*info.This());
573 Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
574 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
575}
576
577
578void Accessors::ScriptLineOffsetSetter(
579 v8::Local<v8::Name> name,
580 v8::Local<v8::Value> value,
581 const v8::PropertyCallbackInfo<void>& info) {
582 UNREACHABLE();
583}
584
585
586Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
587 Isolate* isolate, PropertyAttributes attributes) {
588 Handle<String> name(isolate->factory()->InternalizeOneByteString(
589 STATIC_CHAR_VECTOR("line_offset")));
590 return MakeAccessor(isolate,
591 name,
592 &ScriptLineOffsetGetter,
593 &ScriptLineOffsetSetter,
594 attributes);
595}
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
597
598//
599// Accessors::ScriptType
600//
601
602
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603void Accessors::ScriptTypeGetter(
604 v8::Local<v8::Name> name,
605 const v8::PropertyCallbackInfo<v8::Value>& info) {
606 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
607 DisallowHeapAllocation no_allocation;
608 HandleScope scope(isolate);
609 Object* object = *Utils::OpenHandle(*info.This());
610 Object* res = Script::cast(JSValue::cast(object)->value())->type();
611 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000612}
613
614
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000615void Accessors::ScriptTypeSetter(
616 v8::Local<v8::Name> name,
617 v8::Local<v8::Value> value,
618 const v8::PropertyCallbackInfo<void>& info) {
619 UNREACHABLE();
620}
621
622
623Handle<AccessorInfo> Accessors::ScriptTypeInfo(
624 Isolate* isolate, PropertyAttributes attributes) {
625 Handle<String> name(
626 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
627 return MakeAccessor(isolate,
628 name,
629 &ScriptTypeGetter,
630 &ScriptTypeSetter,
631 attributes);
632}
Steve Blocka7e24c12009-10-30 11:49:00 +0000633
634
635//
636// Accessors::ScriptCompilationType
637//
638
639
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640void Accessors::ScriptCompilationTypeGetter(
641 v8::Local<v8::Name> name,
642 const v8::PropertyCallbackInfo<v8::Value>& info) {
643 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
644 DisallowHeapAllocation no_allocation;
645 HandleScope scope(isolate);
646 Object* object = *Utils::OpenHandle(*info.This());
647 Object* res = Smi::FromInt(
648 Script::cast(JSValue::cast(object)->value())->compilation_type());
649 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000650}
651
652
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653void Accessors::ScriptCompilationTypeSetter(
654 v8::Local<v8::Name> name,
655 v8::Local<v8::Value> value,
656 const v8::PropertyCallbackInfo<void>& info) {
657 UNREACHABLE();
658}
659
660
661Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
662 Isolate* isolate, PropertyAttributes attributes) {
663 Handle<String> name(isolate->factory()->InternalizeOneByteString(
664 STATIC_CHAR_VECTOR("compilation_type")));
665 return MakeAccessor(isolate,
666 name,
667 &ScriptCompilationTypeGetter,
668 &ScriptCompilationTypeSetter,
669 attributes);
670}
Steve Blocka7e24c12009-10-30 11:49:00 +0000671
672
673//
674// Accessors::ScriptGetLineEnds
675//
676
677
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678void Accessors::ScriptLineEndsGetter(
679 v8::Local<v8::Name> name,
680 const v8::PropertyCallbackInfo<v8::Value>& info) {
681 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
Steve Block44f0eee2011-05-26 01:26:41 +0100682 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 Handle<Object> object = Utils::OpenHandle(*info.This());
684 Handle<Script> script(
685 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
686 Script::InitLineEnds(script);
687 DCHECK(script->line_ends()->IsFixedArray());
Steve Blockd0582a62009-12-15 09:54:21 +0000688 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800689 // We do not want anyone to modify this array from JS.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 DCHECK(*line_ends == isolate->heap()->empty_fixed_array() ||
Steve Block44f0eee2011-05-26 01:26:41 +0100691 line_ends->map() == isolate->heap()->fixed_cow_array_map());
692 Handle<JSArray> js_array =
693 isolate->factory()->NewJSArrayWithElements(line_ends);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 info.GetReturnValue().Set(Utils::ToLocal(js_array));
Steve Blocka7e24c12009-10-30 11:49:00 +0000695}
696
697
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698void Accessors::ScriptLineEndsSetter(
699 v8::Local<v8::Name> name,
700 v8::Local<v8::Value> value,
701 const v8::PropertyCallbackInfo<void>& info) {
702 UNREACHABLE();
703}
704
705
706Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
707 Isolate* isolate, PropertyAttributes attributes) {
708 Handle<String> name(isolate->factory()->InternalizeOneByteString(
709 STATIC_CHAR_VECTOR("line_ends")));
710 return MakeAccessor(isolate,
711 name,
712 &ScriptLineEndsGetter,
713 &ScriptLineEndsSetter,
714 attributes);
715}
716
717
718//
719// Accessors::ScriptSourceUrl
720//
721
722
723void Accessors::ScriptSourceUrlGetter(
724 v8::Local<v8::Name> name,
725 const v8::PropertyCallbackInfo<v8::Value>& info) {
726 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
727 DisallowHeapAllocation no_allocation;
728 HandleScope scope(isolate);
729 Object* object = *Utils::OpenHandle(*info.This());
730 Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
731 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
732}
733
734
735void Accessors::ScriptSourceUrlSetter(
736 v8::Local<v8::Name> name,
737 v8::Local<v8::Value> value,
738 const v8::PropertyCallbackInfo<void>& info) {
739 UNREACHABLE();
740}
741
742
743Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
744 Isolate* isolate, PropertyAttributes attributes) {
745 return MakeAccessor(isolate,
746 isolate->factory()->source_url_string(),
747 &ScriptSourceUrlGetter,
748 &ScriptSourceUrlSetter,
749 attributes);
750}
751
752
753//
754// Accessors::ScriptSourceMappingUrl
755//
756
757
758void Accessors::ScriptSourceMappingUrlGetter(
759 v8::Local<v8::Name> name,
760 const v8::PropertyCallbackInfo<v8::Value>& info) {
761 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
762 DisallowHeapAllocation no_allocation;
763 HandleScope scope(isolate);
764 Object* object = *Utils::OpenHandle(*info.This());
765 Object* url =
766 Script::cast(JSValue::cast(object)->value())->source_mapping_url();
767 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
768}
769
770
771void Accessors::ScriptSourceMappingUrlSetter(
772 v8::Local<v8::Name> name,
773 v8::Local<v8::Value> value,
774 const v8::PropertyCallbackInfo<void>& info) {
775 UNREACHABLE();
776}
777
778
779Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
780 Isolate* isolate, PropertyAttributes attributes) {
781 return MakeAccessor(isolate,
782 isolate->factory()->source_mapping_url_string(),
783 &ScriptSourceMappingUrlGetter,
784 &ScriptSourceMappingUrlSetter,
785 attributes);
786}
Steve Blocka7e24c12009-10-30 11:49:00 +0000787
788
789//
790// Accessors::ScriptGetContextData
791//
792
793
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794void Accessors::ScriptContextDataGetter(
795 v8::Local<v8::Name> name,
796 const v8::PropertyCallbackInfo<v8::Value>& info) {
797 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
798 DisallowHeapAllocation no_allocation;
799 HandleScope scope(isolate);
800 Object* object = *Utils::OpenHandle(*info.This());
801 Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
802 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000803}
804
805
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806void Accessors::ScriptContextDataSetter(
807 v8::Local<v8::Name> name,
808 v8::Local<v8::Value> value,
809 const v8::PropertyCallbackInfo<void>& info) {
810 UNREACHABLE();
811}
812
813
814Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
815 Isolate* isolate, PropertyAttributes attributes) {
816 Handle<String> name(isolate->factory()->InternalizeOneByteString(
817 STATIC_CHAR_VECTOR("context_data")));
818 return MakeAccessor(isolate,
819 name,
820 &ScriptContextDataGetter,
821 &ScriptContextDataSetter,
822 attributes);
823}
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
825
826//
Steve Blockd0582a62009-12-15 09:54:21 +0000827// Accessors::ScriptGetEvalFromScript
Steve Blocka7e24c12009-10-30 11:49:00 +0000828//
829
830
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831void Accessors::ScriptEvalFromScriptGetter(
832 v8::Local<v8::Name> name,
833 const v8::PropertyCallbackInfo<v8::Value>& info) {
834 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
835 HandleScope scope(isolate);
836 Handle<Object> object = Utils::OpenHandle(*info.This());
837 Handle<Script> script(
838 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
839 Handle<Object> result = isolate->factory()->undefined_value();
840 if (!script->eval_from_shared()->IsUndefined()) {
Steve Blockd0582a62009-12-15 09:54:21 +0000841 Handle<SharedFunctionInfo> eval_from_shared(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000842 SharedFunctionInfo::cast(script->eval_from_shared()));
Steve Blockd0582a62009-12-15 09:54:21 +0000843 if (eval_from_shared->script()->IsScript()) {
844 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000845 result = Script::GetWrapper(eval_from_script);
Steve Blockd0582a62009-12-15 09:54:21 +0000846 }
847 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848
849 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000850}
851
852
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853void Accessors::ScriptEvalFromScriptSetter(
854 v8::Local<v8::Name> name,
855 v8::Local<v8::Value> value,
856 const v8::PropertyCallbackInfo<void>& info) {
857 UNREACHABLE();
858}
859
860
861Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
862 Isolate* isolate, PropertyAttributes attributes) {
863 Handle<String> name(isolate->factory()->InternalizeOneByteString(
864 STATIC_CHAR_VECTOR("eval_from_script")));
865 return MakeAccessor(isolate,
866 name,
867 &ScriptEvalFromScriptGetter,
868 &ScriptEvalFromScriptSetter,
869 attributes);
870}
Steve Blocka7e24c12009-10-30 11:49:00 +0000871
872
873//
Steve Blockd0582a62009-12-15 09:54:21 +0000874// Accessors::ScriptGetEvalFromScriptPosition
Steve Blocka7e24c12009-10-30 11:49:00 +0000875//
876
877
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878void Accessors::ScriptEvalFromScriptPositionGetter(
879 v8::Local<v8::Name> name,
880 const v8::PropertyCallbackInfo<v8::Value>& info) {
881 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
882 HandleScope scope(isolate);
883 Handle<Object> object = Utils::OpenHandle(*info.This());
884 Handle<Script> script(
885 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
886 Handle<Object> result = isolate->factory()->undefined_value();
887 if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
888 Handle<Code> code(SharedFunctionInfo::cast(
889 script->eval_from_shared())->code());
890 result = Handle<Object>(
891 Smi::FromInt(code->SourcePosition(code->instruction_start() +
892 script->eval_from_instructions_offset()->value())),
893 isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000894 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000896}
897
898
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899void Accessors::ScriptEvalFromScriptPositionSetter(
900 v8::Local<v8::Name> name,
901 v8::Local<v8::Value> value,
902 const v8::PropertyCallbackInfo<void>& info) {
903 UNREACHABLE();
904}
905
906
907Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
908 Isolate* isolate, PropertyAttributes attributes) {
909 Handle<String> name(isolate->factory()->InternalizeOneByteString(
910 STATIC_CHAR_VECTOR("eval_from_script_position")));
911 return MakeAccessor(isolate,
912 name,
913 &ScriptEvalFromScriptPositionGetter,
914 &ScriptEvalFromScriptPositionSetter,
915 attributes);
916}
Steve Blockd0582a62009-12-15 09:54:21 +0000917
918
919//
920// Accessors::ScriptGetEvalFromFunctionName
921//
922
923
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924void Accessors::ScriptEvalFromFunctionNameGetter(
925 v8::Local<v8::Name> name,
926 const v8::PropertyCallbackInfo<v8::Value>& info) {
927 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
928 HandleScope scope(isolate);
929 Handle<Object> object = Utils::OpenHandle(*info.This());
930 Handle<Script> script(
931 Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
932 Handle<Object> result;
933 Handle<SharedFunctionInfo> shared(
934 SharedFunctionInfo::cast(script->eval_from_shared()));
Steve Blockd0582a62009-12-15 09:54:21 +0000935 // Find the name of the function calling eval.
936 if (!shared->name()->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 result = Handle<Object>(shared->name(), isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000938 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 result = Handle<Object>(shared->inferred_name(), isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000940 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blockd0582a62009-12-15 09:54:21 +0000942}
943
944
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945void Accessors::ScriptEvalFromFunctionNameSetter(
946 v8::Local<v8::Name> name,
947 v8::Local<v8::Value> value,
948 const v8::PropertyCallbackInfo<void>& info) {
949 UNREACHABLE();
950}
951
952
953Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
954 Isolate* isolate, PropertyAttributes attributes) {
955 Handle<String> name(isolate->factory()->InternalizeOneByteString(
956 STATIC_CHAR_VECTOR("eval_from_function_name")));
957 return MakeAccessor(isolate,
958 name,
959 &ScriptEvalFromFunctionNameGetter,
960 &ScriptEvalFromFunctionNameSetter,
961 attributes);
962}
Steve Blocka7e24c12009-10-30 11:49:00 +0000963
964
965//
966// Accessors::FunctionPrototype
967//
968
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969static Handle<Object> GetFunctionPrototype(Isolate* isolate,
970 Handle<JSFunction> function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 if (!function->has_prototype()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
973 JSFunction::SetPrototype(function, proto);
Steve Blocka7e24c12009-10-30 11:49:00 +0000974 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 return Handle<Object>(function->prototype(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000976}
977
978
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400979MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
980 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981 Handle<Object> old_value;
982 bool is_observed = function->map()->is_observed();
983 if (is_observed) {
984 if (function->has_prototype())
985 old_value = handle(function->prototype(), isolate);
986 else
987 old_value = isolate->factory()->NewFunctionPrototype(function);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100988 }
989
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 JSFunction::SetPrototype(function, value);
991 DCHECK(function->prototype() == *value);
992
993 if (is_observed && !old_value->SameValue(*value)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400994 MaybeHandle<Object> result = JSObject::EnqueueChangeRecord(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 function, "update", isolate->factory()->prototype_string(), old_value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400996 if (result.is_null()) return MaybeHandle<Object>();
John Reck59135872010-11-02 12:39:01 -0700997 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 return function;
1000}
1001
1002
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001003MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
1004 Handle<Object> prototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005 DCHECK(function->should_have_prototype());
1006 Isolate* isolate = function->GetIsolate();
1007 return SetFunctionPrototype(isolate, function, prototype);
1008}
1009
1010
1011void Accessors::FunctionPrototypeGetter(
1012 v8::Local<v8::Name> name,
1013 const v8::PropertyCallbackInfo<v8::Value>& info) {
1014 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1015 HandleScope scope(isolate);
1016 Handle<JSFunction> function =
1017 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1018 Handle<Object> result = GetFunctionPrototype(isolate, function);
1019 info.GetReturnValue().Set(Utils::ToLocal(result));
1020}
1021
1022
1023void Accessors::FunctionPrototypeSetter(
1024 v8::Local<v8::Name> name,
1025 v8::Local<v8::Value> val,
1026 const v8::PropertyCallbackInfo<void>& info) {
1027 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1028 HandleScope scope(isolate);
1029 Handle<Object> value = Utils::OpenHandle(*val);
1030 if (SetPropertyOnInstanceIfInherited(isolate, info, name, value)) {
1031 return;
1032 }
1033 Handle<JSFunction> object =
1034 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001035 if (SetFunctionPrototype(isolate, object, value).is_null()) {
1036 isolate->OptionalRescheduleException(false);
1037 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038}
1039
1040
1041Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
1042 Isolate* isolate, PropertyAttributes attributes) {
1043 return MakeAccessor(isolate,
1044 isolate->factory()->prototype_string(),
1045 &FunctionPrototypeGetter,
1046 &FunctionPrototypeSetter,
1047 attributes);
1048}
Steve Blocka7e24c12009-10-30 11:49:00 +00001049
1050
1051//
1052// Accessors::FunctionLength
1053//
1054
1055
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056void Accessors::FunctionLengthGetter(
1057 v8::Local<v8::Name> name,
1058 const v8::PropertyCallbackInfo<v8::Value>& info) {
1059 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1060 HandleScope scope(isolate);
1061 Handle<JSFunction> function =
1062 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1063
1064 int length = 0;
1065 if (function->shared()->is_compiled()) {
1066 length = function->shared()->length();
1067 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00001068 // If the function isn't compiled yet, the length is not computed
1069 // correctly yet. Compile it now and return the right length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070 if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
1071 length = function->shared()->length();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001072 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 if (isolate->has_pending_exception()) {
1074 isolate->OptionalRescheduleException(false);
1075 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 Handle<Object> result(Smi::FromInt(length), isolate);
1078 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001079}
1080
1081
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082void Accessors::FunctionLengthSetter(
1083 v8::Local<v8::Name> name,
1084 v8::Local<v8::Value> val,
1085 const v8::PropertyCallbackInfo<void>& info) {
1086 // Function length is non writable, non configurable.
1087 UNREACHABLE();
1088}
1089
1090
1091Handle<AccessorInfo> Accessors::FunctionLengthInfo(
1092 Isolate* isolate, PropertyAttributes attributes) {
1093 return MakeAccessor(isolate,
1094 isolate->factory()->length_string(),
1095 &FunctionLengthGetter,
1096 &FunctionLengthSetter,
1097 attributes);
1098}
Steve Blocka7e24c12009-10-30 11:49:00 +00001099
1100
1101//
1102// Accessors::FunctionName
1103//
1104
1105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106void Accessors::FunctionNameGetter(
1107 v8::Local<v8::Name> name,
1108 const v8::PropertyCallbackInfo<v8::Value>& info) {
1109 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1110 HandleScope scope(isolate);
1111 Handle<JSFunction> function =
1112 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1113 Handle<Object> result(function->shared()->name(), isolate);
1114 info.GetReturnValue().Set(Utils::ToLocal(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001115}
1116
1117
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118void Accessors::FunctionNameSetter(
1119 v8::Local<v8::Name> name,
1120 v8::Local<v8::Value> val,
1121 const v8::PropertyCallbackInfo<void>& info) {
1122 // Function name is non writable, non configurable.
1123 UNREACHABLE();
1124}
1125
1126
1127Handle<AccessorInfo> Accessors::FunctionNameInfo(
1128 Isolate* isolate, PropertyAttributes attributes) {
1129 return MakeAccessor(isolate,
1130 isolate->factory()->name_string(),
1131 &FunctionNameGetter,
1132 &FunctionNameSetter,
1133 attributes);
1134}
Steve Blocka7e24c12009-10-30 11:49:00 +00001135
1136
1137//
1138// Accessors::FunctionArguments
1139//
1140
Ben Murdochb0fe1622011-05-05 13:52:32 +01001141
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001142static Handle<Object> ArgumentsForInlinedFunction(
Ben Murdochb0fe1622011-05-05 13:52:32 +01001143 JavaScriptFrame* frame,
1144 Handle<JSFunction> inlined_function,
1145 int inlined_frame_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146 Isolate* isolate = inlined_function->GetIsolate();
1147 Factory* factory = isolate->factory();
1148 SlotRefValueBuilder slot_refs(
1149 frame,
1150 inlined_frame_index,
1151 inlined_function->shared()->formal_parameter_count());
1152
1153 int args_count = slot_refs.args_length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001154 Handle<JSObject> arguments =
Steve Block44f0eee2011-05-26 01:26:41 +01001155 factory->NewArgumentsObject(inlined_function, args_count);
1156 Handle<FixedArray> array = factory->NewFixedArray(args_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 slot_refs.Prepare(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001158 for (int i = 0; i < args_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001159 Handle<Object> value = slot_refs.GetNext(isolate, 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001160 array->set(i, *value);
1161 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001162 slot_refs.Finish(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001163 arguments->set_elements(*array);
1164
1165 // Return the freshly allocated arguments object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166 return arguments;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001167}
1168
Steve Blocka7e24c12009-10-30 11:49:00 +00001169
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001170static int FindFunctionInFrame(JavaScriptFrame* frame,
1171 Handle<JSFunction> function) {
1172 DisallowHeapAllocation no_allocation;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001173 List<JSFunction*> functions(2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 frame->GetFunctions(&functions);
1175 for (int i = functions.length() - 1; i >= 0; i--) {
1176 if (functions[i] == *function) return i;
1177 }
1178 return -1;
1179}
1180
1181
1182Handle<Object> GetFunctionArguments(Isolate* isolate,
1183 Handle<JSFunction> function) {
1184 if (function->shared()->native()) return isolate->factory()->null_value();
1185
1186 // Find the top invocation of the function by traversing frames.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001187 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 JavaScriptFrame* frame = it.frame();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 int function_index = FindFunctionInFrame(frame, function);
1190 if (function_index < 0) continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001191
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 if (function_index > 0) {
1193 // The function in question was inlined. Inlined functions have the
1194 // correct number of arguments and no allocated arguments object, so
1195 // we can construct a fresh one by interpreting the function's
1196 // deoptimization input data.
1197 return ArgumentsForInlinedFunction(frame, function, function_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199
1200 if (!frame->is_optimized()) {
1201 // If there is an arguments variable in the stack, we return that.
1202 Handle<ScopeInfo> scope_info(function->shared()->scope_info());
1203 int index = scope_info->StackSlotIndex(
1204 isolate->heap()->arguments_string());
1205 if (index >= 0) {
1206 Handle<Object> arguments(frame->GetExpression(index), isolate);
1207 if (!arguments->IsArgumentsMarker()) return arguments;
1208 }
1209 }
1210
1211 // If there is no arguments variable in the stack or we have an
1212 // optimized frame, we find the frame that holds the actual arguments
1213 // passed to the function.
1214 it.AdvanceToArgumentsFrame();
1215 frame = it.frame();
1216
1217 // Get the number of arguments and construct an arguments object
1218 // mirror for the right frame.
1219 const int length = frame->ComputeParametersCount();
1220 Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
1221 function, length);
1222 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
1223
1224 // Copy the parameters to the arguments object.
1225 DCHECK(array->length() == length);
1226 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
1227 arguments->set_elements(*array);
1228
1229 // Return the freshly allocated arguments object.
1230 return arguments;
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 }
1232
1233 // No frame corresponding to the given function found. Return null.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234 return isolate->factory()->null_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001235}
1236
1237
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
1239 return GetFunctionArguments(function->GetIsolate(), function);
1240}
1241
1242
1243void Accessors::FunctionArgumentsGetter(
1244 v8::Local<v8::Name> name,
1245 const v8::PropertyCallbackInfo<v8::Value>& info) {
1246 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1247 HandleScope scope(isolate);
1248 Handle<JSFunction> function =
1249 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1250 Handle<Object> result = GetFunctionArguments(isolate, function);
1251 info.GetReturnValue().Set(Utils::ToLocal(result));
1252}
1253
1254
1255void Accessors::FunctionArgumentsSetter(
1256 v8::Local<v8::Name> name,
1257 v8::Local<v8::Value> val,
1258 const v8::PropertyCallbackInfo<void>& info) {
1259 // Function arguments is non writable, non configurable.
1260 UNREACHABLE();
1261}
1262
1263
1264Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
1265 Isolate* isolate, PropertyAttributes attributes) {
1266 return MakeAccessor(isolate,
1267 isolate->factory()->arguments_string(),
1268 &FunctionArgumentsGetter,
1269 &FunctionArgumentsSetter,
1270 attributes);
1271}
Steve Blocka7e24c12009-10-30 11:49:00 +00001272
1273
1274//
1275// Accessors::FunctionCaller
1276//
1277
1278
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279static inline bool AllowAccessToFunction(Context* current_context,
1280 JSFunction* function) {
1281 return current_context->HasSameSecurityTokenAs(function->context());
Steve Block44f0eee2011-05-26 01:26:41 +01001282}
1283
1284
Ben Murdoch257744e2011-11-30 15:57:28 +00001285class FrameFunctionIterator {
1286 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
1288 : isolate_(isolate),
1289 frame_iterator_(isolate),
Ben Murdoch257744e2011-11-30 15:57:28 +00001290 functions_(2),
1291 index_(0) {
1292 GetFunctions();
1293 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001294 JSFunction* next() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 while (true) {
1296 if (functions_.length() == 0) return NULL;
1297 JSFunction* next_function = functions_[index_];
1298 index_--;
1299 if (index_ < 0) {
1300 GetFunctions();
1301 }
1302 // Skip functions from other origins.
1303 if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
1304 return next_function;
Ben Murdoch257744e2011-11-30 15:57:28 +00001305 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001306 }
1307
1308 // Iterate through functions until the first occurence of 'function'.
1309 // Returns true if 'function' is found, and false if the iterator ends
1310 // without finding it.
1311 bool Find(JSFunction* function) {
1312 JSFunction* next_function;
1313 do {
1314 next_function = next();
1315 if (next_function == function) return true;
1316 } while (next_function != NULL);
1317 return false;
1318 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001319
Ben Murdoch257744e2011-11-30 15:57:28 +00001320 private:
1321 void GetFunctions() {
1322 functions_.Rewind(0);
1323 if (frame_iterator_.done()) return;
1324 JavaScriptFrame* frame = frame_iterator_.frame();
1325 frame->GetFunctions(&functions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 DCHECK(functions_.length() > 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001327 frame_iterator_.Advance();
1328 index_ = functions_.length() - 1;
1329 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 Isolate* isolate_;
Ben Murdoch257744e2011-11-30 15:57:28 +00001331 JavaScriptFrameIterator frame_iterator_;
1332 List<JSFunction*> functions_;
1333 int index_;
1334};
1335
1336
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
1338 Handle<JSFunction> function) {
1339 DisallowHeapAllocation no_allocation;
1340 FrameFunctionIterator it(isolate, no_allocation);
1341 if (function->shared()->native()) {
1342 return MaybeHandle<JSFunction>();
1343 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001344 // Find the function from the frames.
1345 if (!it.Find(*function)) {
1346 // No frame corresponding to the given function found. Return null.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 return MaybeHandle<JSFunction>();
Steve Blocka7e24c12009-10-30 11:49:00 +00001348 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001349 // Find previously called non-toplevel function.
1350 JSFunction* caller;
1351 do {
1352 caller = it.next();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 if (caller == NULL) return MaybeHandle<JSFunction>();
Ben Murdoch257744e2011-11-30 15:57:28 +00001354 } while (caller->shared()->is_toplevel());
1355
1356 // If caller is a built-in function and caller's caller is also built-in,
1357 // use that instead.
1358 JSFunction* potential_caller = caller;
1359 while (potential_caller != NULL && potential_caller->IsBuiltin()) {
1360 caller = potential_caller;
1361 potential_caller = it.next();
1362 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 if (!caller->shared()->native() && potential_caller != NULL) {
1364 caller = potential_caller;
1365 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001366 // If caller is bound, return null. This is compatible with JSC, and
1367 // allows us to make bound functions use the strict function map
1368 // and its associated throwing caller and arguments.
1369 if (caller->shared()->bound()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001370 return MaybeHandle<JSFunction>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001371 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 // Censor if the caller is not a sloppy mode function.
1373 // Change from ES5, which used to throw, see:
1374 // https://bugs.ecmascript.org/show_bug.cgi?id=310
1375 if (caller->shared()->strict_mode() == STRICT) {
1376 return MaybeHandle<JSFunction>();
1377 }
1378 // Don't return caller from another security context.
1379 if (!AllowAccessToFunction(isolate->context(), caller)) {
1380 return MaybeHandle<JSFunction>();
1381 }
1382 return Handle<JSFunction>(caller);
Steve Blocka7e24c12009-10-30 11:49:00 +00001383}
1384
1385
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386void Accessors::FunctionCallerGetter(
1387 v8::Local<v8::Name> name,
1388 const v8::PropertyCallbackInfo<v8::Value>& info) {
1389 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1390 HandleScope scope(isolate);
1391 Handle<JSFunction> function =
1392 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1393 Handle<Object> result;
1394 MaybeHandle<JSFunction> maybe_caller;
1395 maybe_caller = FindCaller(isolate, function);
1396 Handle<JSFunction> caller;
1397 if (maybe_caller.ToHandle(&caller)) {
1398 result = caller;
1399 } else {
1400 result = isolate->factory()->null_value();
1401 }
1402 info.GetReturnValue().Set(Utils::ToLocal(result));
1403}
1404
1405
1406void Accessors::FunctionCallerSetter(
1407 v8::Local<v8::Name> name,
1408 v8::Local<v8::Value> val,
1409 const v8::PropertyCallbackInfo<void>& info) {
1410 // Function caller is non writable, non configurable.
1411 UNREACHABLE();
1412}
1413
1414
1415Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1416 Isolate* isolate, PropertyAttributes attributes) {
1417 return MakeAccessor(isolate,
1418 isolate->factory()->caller_string(),
1419 &FunctionCallerGetter,
1420 &FunctionCallerSetter,
1421 attributes);
1422}
Steve Blocka7e24c12009-10-30 11:49:00 +00001423
1424
1425//
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426// Accessors::MakeModuleExport
Steve Blocka7e24c12009-10-30 11:49:00 +00001427//
1428
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429static void ModuleGetExport(
1430 v8::Local<v8::String> property,
1431 const v8::PropertyCallbackInfo<v8::Value>& info) {
1432 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1433 Context* context = Context::cast(instance->context());
1434 DCHECK(context->IsModuleContext());
1435 int slot = info.Data()->Int32Value();
1436 Object* value = context->get(slot);
1437 Isolate* isolate = instance->GetIsolate();
1438 if (value->IsTheHole()) {
1439 Handle<String> name = v8::Utils::OpenHandle(*property);
Steve Blocka7e24c12009-10-30 11:49:00 +00001440
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001441 Handle<Object> exception;
1442 MaybeHandle<Object> maybe = isolate->factory()->NewReferenceError(
1443 "not_defined", HandleVector(&name, 1));
1444 if (!maybe.ToHandle(&exception)) {
1445 isolate->OptionalRescheduleException(false);
1446 return;
1447 }
1448
1449 isolate->ScheduleThrow(*exception);
1450 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001453}
1454
1455
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001456static void ModuleSetExport(
1457 v8::Local<v8::String> property,
1458 v8::Local<v8::Value> value,
1459 const v8::PropertyCallbackInfo<v8::Value>& info) {
1460 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
1461 Context* context = Context::cast(instance->context());
1462 DCHECK(context->IsModuleContext());
1463 int slot = info.Data()->Int32Value();
1464 Object* old_value = context->get(slot);
1465 Isolate* isolate = context->GetIsolate();
1466 if (old_value->IsTheHole()) {
1467 Handle<String> name = v8::Utils::OpenHandle(*property);
1468 Handle<Object> exception;
1469 MaybeHandle<Object> maybe = isolate->factory()->NewReferenceError(
1470 "not_defined", HandleVector(&name, 1));
1471 if (!maybe.ToHandle(&exception)) {
1472 isolate->OptionalRescheduleException(false);
1473 return;
1474 }
1475
1476 isolate->ScheduleThrow(*exception);
1477 return;
1478 }
1479 context->set(slot, *v8::Utils::OpenHandle(*value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001480}
1481
1482
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001483Handle<AccessorInfo> Accessors::MakeModuleExport(
1484 Handle<String> name,
1485 int index,
1486 PropertyAttributes attributes) {
1487 Isolate* isolate = name->GetIsolate();
1488 Factory* factory = isolate->factory();
1489 Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
1490 info->set_property_attributes(attributes);
1491 info->set_all_can_read(true);
1492 info->set_all_can_write(true);
1493 info->set_name(*name);
1494 info->set_data(Smi::FromInt(index));
1495 Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
1496 Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
1497 info->set_getter(*getter);
1498 if (!(attributes & ReadOnly)) info->set_setter(*setter);
1499 return info;
1500}
1501
Steve Blocka7e24c12009-10-30 11:49:00 +00001502
1503} } // namespace v8::internal