blob: 08ef41b9f7ea60d95911fd4caa97d299d7bee20c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "accessors.h"
31#include "execution.h"
32#include "factory.h"
33#include "scopeinfo.h"
34#include "top.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36namespace v8 {
37namespace internal {
38
39
40template <class C>
41static C* FindInPrototypeChain(Object* obj, bool* found_it) {
42 ASSERT(!*found_it);
43 while (!Is<C>(obj)) {
44 if (obj == Heap::null_value()) return NULL;
45 obj = obj->GetPrototype();
46 }
47 *found_it = true;
48 return C::cast(obj);
49}
50
51
52// Entry point that never should be called.
John Reck59135872010-11-02 12:39:01 -070053MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +000054 UNREACHABLE();
55 return NULL;
56}
57
58
59Object* Accessors::IllegalGetAccessor(Object* object, void*) {
60 UNREACHABLE();
61 return object;
62}
63
64
John Reck59135872010-11-02 12:39:01 -070065MaybeObject* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +000066 // According to ECMA-262, section 8.6.2.2, page 28, setting
67 // read-only properties must be silently ignored.
68 return value;
69}
70
71
72//
73// Accessors::ArrayLength
74//
75
76
John Reck59135872010-11-02 12:39:01 -070077MaybeObject* Accessors::ArrayGetLength(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +000078 // Traverse the prototype chain until we reach an array.
79 bool found_it = false;
80 JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it);
81 if (!found_it) return Smi::FromInt(0);
82 return holder->length();
83}
84
85
86// The helper function will 'flatten' Number objects.
87Object* Accessors::FlattenNumber(Object* value) {
88 if (value->IsNumber() || !value->IsJSValue()) return value;
89 JSValue* wrapper = JSValue::cast(value);
90 ASSERT(
91 Top::context()->global_context()->number_function()->has_initial_map());
92 Map* number_map =
93 Top::context()->global_context()->number_function()->initial_map();
94 if (wrapper->map() == number_map) return wrapper->value();
95 return value;
96}
97
98
John Reck59135872010-11-02 12:39:01 -070099MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000100 value = FlattenNumber(value);
101
102 // Need to call methods that may trigger GC.
103 HandleScope scope;
104
105 // Protect raw pointers.
106 Handle<JSObject> object_handle(object);
107 Handle<Object> value_handle(value);
108
109 bool has_exception;
110 Handle<Object> uint32_v = Execution::ToUint32(value_handle, &has_exception);
111 if (has_exception) return Failure::Exception();
112 Handle<Object> number_v = Execution::ToNumber(value_handle, &has_exception);
113 if (has_exception) return Failure::Exception();
114
115 // Restore raw pointers,
116 object = *object_handle;
117 value = *value_handle;
118
119 if (uint32_v->Number() == number_v->Number()) {
120 if (object->IsJSArray()) {
121 return JSArray::cast(object)->SetElementsLength(*uint32_v);
122 } else {
123 // This means one of the object's prototypes is a JSArray and
124 // the object does not have a 'length' property.
125 // Calling SetProperty causes an infinite loop.
126 return object->IgnoreAttributesAndSetLocalProperty(Heap::length_symbol(),
127 value, NONE);
128 }
129 }
130 return Top::Throw(*Factory::NewRangeError("invalid_array_length",
131 HandleVector<Object>(NULL, 0)));
132}
133
134
135const AccessorDescriptor Accessors::ArrayLength = {
136 ArrayGetLength,
137 ArraySetLength,
138 0
139};
140
141
142//
143// Accessors::StringLength
144//
145
146
John Reck59135872010-11-02 12:39:01 -0700147MaybeObject* Accessors::StringGetLength(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 Object* value = object;
149 if (object->IsJSValue()) value = JSValue::cast(object)->value();
150 if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
151 // If object is not a string we return 0 to be compatible with WebKit.
152 // Note: Firefox returns the length of ToString(object).
153 return Smi::FromInt(0);
154}
155
156
157const AccessorDescriptor Accessors::StringLength = {
158 StringGetLength,
159 IllegalSetter,
160 0
161};
162
163
164//
165// Accessors::ScriptSource
166//
167
168
John Reck59135872010-11-02 12:39:01 -0700169MaybeObject* Accessors::ScriptGetSource(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 Object* script = JSValue::cast(object)->value();
171 return Script::cast(script)->source();
172}
173
174
175const AccessorDescriptor Accessors::ScriptSource = {
176 ScriptGetSource,
177 IllegalSetter,
178 0
179};
180
181
182//
183// Accessors::ScriptName
184//
185
186
John Reck59135872010-11-02 12:39:01 -0700187MaybeObject* Accessors::ScriptGetName(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000188 Object* script = JSValue::cast(object)->value();
189 return Script::cast(script)->name();
190}
191
192
193const AccessorDescriptor Accessors::ScriptName = {
194 ScriptGetName,
195 IllegalSetter,
196 0
197};
198
199
200//
201// Accessors::ScriptId
202//
203
204
John Reck59135872010-11-02 12:39:01 -0700205MaybeObject* Accessors::ScriptGetId(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 Object* script = JSValue::cast(object)->value();
207 return Script::cast(script)->id();
208}
209
210
211const AccessorDescriptor Accessors::ScriptId = {
212 ScriptGetId,
213 IllegalSetter,
214 0
215};
216
217
218//
219// Accessors::ScriptLineOffset
220//
221
222
John Reck59135872010-11-02 12:39:01 -0700223MaybeObject* Accessors::ScriptGetLineOffset(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000224 Object* script = JSValue::cast(object)->value();
225 return Script::cast(script)->line_offset();
226}
227
228
229const AccessorDescriptor Accessors::ScriptLineOffset = {
230 ScriptGetLineOffset,
231 IllegalSetter,
232 0
233};
234
235
236//
237// Accessors::ScriptColumnOffset
238//
239
240
John Reck59135872010-11-02 12:39:01 -0700241MaybeObject* Accessors::ScriptGetColumnOffset(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 Object* script = JSValue::cast(object)->value();
243 return Script::cast(script)->column_offset();
244}
245
246
247const AccessorDescriptor Accessors::ScriptColumnOffset = {
248 ScriptGetColumnOffset,
249 IllegalSetter,
250 0
251};
252
253
254//
255// Accessors::ScriptData
256//
257
258
John Reck59135872010-11-02 12:39:01 -0700259MaybeObject* Accessors::ScriptGetData(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 Object* script = JSValue::cast(object)->value();
261 return Script::cast(script)->data();
262}
263
264
265const AccessorDescriptor Accessors::ScriptData = {
266 ScriptGetData,
267 IllegalSetter,
268 0
269};
270
271
272//
273// Accessors::ScriptType
274//
275
276
John Reck59135872010-11-02 12:39:01 -0700277MaybeObject* Accessors::ScriptGetType(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 Object* script = JSValue::cast(object)->value();
279 return Script::cast(script)->type();
280}
281
282
283const AccessorDescriptor Accessors::ScriptType = {
284 ScriptGetType,
285 IllegalSetter,
286 0
287};
288
289
290//
291// Accessors::ScriptCompilationType
292//
293
294
John Reck59135872010-11-02 12:39:01 -0700295MaybeObject* Accessors::ScriptGetCompilationType(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000296 Object* script = JSValue::cast(object)->value();
297 return Script::cast(script)->compilation_type();
298}
299
300
301const AccessorDescriptor Accessors::ScriptCompilationType = {
302 ScriptGetCompilationType,
303 IllegalSetter,
304 0
305};
306
307
308//
309// Accessors::ScriptGetLineEnds
310//
311
312
John Reck59135872010-11-02 12:39:01 -0700313MaybeObject* Accessors::ScriptGetLineEnds(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 HandleScope scope;
315 Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
316 InitScriptLineEnds(script);
Steve Blockd0582a62009-12-15 09:54:21 +0000317 ASSERT(script->line_ends()->IsFixedArray());
318 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800319 // We do not want anyone to modify this array from JS.
320 ASSERT(*line_ends == Heap::empty_fixed_array() ||
321 line_ends->map() == Heap::fixed_cow_array_map());
322 Handle<JSArray> js_array = Factory::NewJSArrayWithElements(line_ends);
Steve Blockd0582a62009-12-15 09:54:21 +0000323 return *js_array;
Steve Blocka7e24c12009-10-30 11:49:00 +0000324}
325
326
327const AccessorDescriptor Accessors::ScriptLineEnds = {
328 ScriptGetLineEnds,
329 IllegalSetter,
330 0
331};
332
333
334//
335// Accessors::ScriptGetContextData
336//
337
338
John Reck59135872010-11-02 12:39:01 -0700339MaybeObject* Accessors::ScriptGetContextData(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 Object* script = JSValue::cast(object)->value();
341 return Script::cast(script)->context_data();
342}
343
344
345const AccessorDescriptor Accessors::ScriptContextData = {
346 ScriptGetContextData,
347 IllegalSetter,
348 0
349};
350
351
352//
Steve Blockd0582a62009-12-15 09:54:21 +0000353// Accessors::ScriptGetEvalFromScript
Steve Blocka7e24c12009-10-30 11:49:00 +0000354//
355
356
John Reck59135872010-11-02 12:39:01 -0700357MaybeObject* Accessors::ScriptGetEvalFromScript(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 Object* script = JSValue::cast(object)->value();
Steve Blockd0582a62009-12-15 09:54:21 +0000359 if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
360 Handle<SharedFunctionInfo> eval_from_shared(
361 SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
362
363 if (eval_from_shared->script()->IsScript()) {
364 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
365 return *GetScriptWrapper(eval_from_script);
366 }
367 }
368 return Heap::undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000369}
370
371
Steve Blockd0582a62009-12-15 09:54:21 +0000372const AccessorDescriptor Accessors::ScriptEvalFromScript = {
373 ScriptGetEvalFromScript,
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 IllegalSetter,
375 0
376};
377
378
379//
Steve Blockd0582a62009-12-15 09:54:21 +0000380// Accessors::ScriptGetEvalFromScriptPosition
Steve Blocka7e24c12009-10-30 11:49:00 +0000381//
382
383
John Reck59135872010-11-02 12:39:01 -0700384MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 HandleScope scope;
386 Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
387
388 // If this is not a script compiled through eval there is no eval position.
389 int compilation_type = Smi::cast(script->compilation_type())->value();
390 if (compilation_type != Script::COMPILATION_TYPE_EVAL) {
391 return Heap::undefined_value();
392 }
393
394 // Get the function from where eval was called and find the source position
395 // from the instruction offset.
Steve Blockd0582a62009-12-15 09:54:21 +0000396 Handle<Code> code(SharedFunctionInfo::cast(
397 script->eval_from_shared())->code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 return Smi::FromInt(code->SourcePosition(code->instruction_start() +
399 script->eval_from_instructions_offset()->value()));
400}
401
402
Steve Blockd0582a62009-12-15 09:54:21 +0000403const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
404 ScriptGetEvalFromScriptPosition,
405 IllegalSetter,
406 0
407};
408
409
410//
411// Accessors::ScriptGetEvalFromFunctionName
412//
413
414
John Reck59135872010-11-02 12:39:01 -0700415MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) {
Steve Blockd0582a62009-12-15 09:54:21 +0000416 Object* script = JSValue::cast(object)->value();
417 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
418 Script::cast(script)->eval_from_shared()));
419
420
421 // Find the name of the function calling eval.
422 if (!shared->name()->IsUndefined()) {
423 return shared->name();
424 } else {
425 return shared->inferred_name();
426 }
427}
428
429
430const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
431 ScriptGetEvalFromFunctionName,
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 IllegalSetter,
433 0
434};
435
436
437//
438// Accessors::FunctionPrototype
439//
440
441
John Reck59135872010-11-02 12:39:01 -0700442MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 bool found_it = false;
444 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
445 if (!found_it) return Heap::undefined_value();
446 if (!function->has_prototype()) {
John Reck59135872010-11-02 12:39:01 -0700447 Object* prototype;
448 { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function);
449 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
450 }
451 Object* result;
452 { MaybeObject* maybe_result = function->SetPrototype(prototype);
453 if (!maybe_result->ToObject(&result)) return maybe_result;
454 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 }
456 return function->prototype();
457}
458
459
John Reck59135872010-11-02 12:39:01 -0700460MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
461 Object* value,
462 void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 bool found_it = false;
464 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
465 if (!found_it) return Heap::undefined_value();
466 if (function->has_initial_map()) {
467 // If the function has allocated the initial map
468 // replace it with a copy containing the new prototype.
John Reck59135872010-11-02 12:39:01 -0700469 Object* new_map;
470 { MaybeObject* maybe_new_map =
471 function->initial_map()->CopyDropTransitions();
472 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
473 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 function->set_initial_map(Map::cast(new_map));
475 }
John Reck59135872010-11-02 12:39:01 -0700476 Object* prototype;
477 { MaybeObject* maybe_prototype = function->SetPrototype(value);
478 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
479 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 ASSERT(function->prototype() == value);
481 return function;
482}
483
484
485const AccessorDescriptor Accessors::FunctionPrototype = {
486 FunctionGetPrototype,
487 FunctionSetPrototype,
488 0
489};
490
491
492//
493// Accessors::FunctionLength
494//
495
496
John Reck59135872010-11-02 12:39:01 -0700497MaybeObject* Accessors::FunctionGetLength(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 bool found_it = false;
499 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
500 if (!found_it) return Smi::FromInt(0);
501 // Check if already compiled.
Iain Merrick75681382010-08-19 15:07:18 +0100502 if (!function->shared()->is_compiled()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 // If the function isn't compiled yet, the length is not computed
504 // correctly yet. Compile it now and return the right length.
505 HandleScope scope;
Leon Clarke4515c472010-02-03 11:58:03 +0000506 Handle<SharedFunctionInfo> shared(function->shared());
507 if (!CompileLazyShared(shared, KEEP_EXCEPTION)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000508 return Failure::Exception();
509 }
Leon Clarke4515c472010-02-03 11:58:03 +0000510 return Smi::FromInt(shared->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 } else {
512 return Smi::FromInt(function->shared()->length());
513 }
514}
515
516
517const AccessorDescriptor Accessors::FunctionLength = {
518 FunctionGetLength,
519 ReadOnlySetAccessor,
520 0
521};
522
523
524//
525// Accessors::FunctionName
526//
527
528
John Reck59135872010-11-02 12:39:01 -0700529MaybeObject* Accessors::FunctionGetName(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 bool found_it = false;
531 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
532 if (!found_it) return Heap::undefined_value();
533 return holder->shared()->name();
534}
535
536
537const AccessorDescriptor Accessors::FunctionName = {
538 FunctionGetName,
539 ReadOnlySetAccessor,
540 0
541};
542
543
544//
545// Accessors::FunctionArguments
546//
547
548
John Reck59135872010-11-02 12:39:01 -0700549MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 HandleScope scope;
551 bool found_it = false;
552 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
553 if (!found_it) return Heap::undefined_value();
554 Handle<JSFunction> function(holder);
555
556 // Find the top invocation of the function by traversing frames.
557 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
558 // Skip all frames that aren't invocations of the given function.
559 JavaScriptFrame* frame = it.frame();
560 if (frame->function() != *function) continue;
561
562 // If there is an arguments variable in the stack, we return that.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100563 int index = function->shared()->scope_info()->
564 StackSlotIndex(Heap::arguments_symbol());
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 if (index >= 0) {
566 Handle<Object> arguments = Handle<Object>(frame->GetExpression(index));
567 if (!arguments->IsTheHole()) return *arguments;
568 }
569
570 // If there isn't an arguments variable in the stack, we need to
571 // find the frame that holds the actual arguments passed to the
572 // function on the stack.
573 it.AdvanceToArgumentsFrame();
574 frame = it.frame();
575
576 // Get the number of arguments and construct an arguments object
577 // mirror for the right frame.
578 const int length = frame->GetProvidedParametersCount();
579 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
580 Handle<FixedArray> array = Factory::NewFixedArray(length);
581
582 // Copy the parameters to the arguments object.
583 ASSERT(array->length() == length);
584 for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
585 arguments->set_elements(*array);
586
587 // Return the freshly allocated arguments object.
588 return *arguments;
589 }
590
591 // No frame corresponding to the given function found. Return null.
592 return Heap::null_value();
593}
594
595
596const AccessorDescriptor Accessors::FunctionArguments = {
597 FunctionGetArguments,
598 ReadOnlySetAccessor,
599 0
600};
601
602
603//
604// Accessors::FunctionCaller
605//
606
607
John Reck59135872010-11-02 12:39:01 -0700608MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000609 HandleScope scope;
John Reck59135872010-11-02 12:39:01 -0700610 AssertNoAllocation no_alloc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 bool found_it = false;
612 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
613 if (!found_it) return Heap::undefined_value();
614 Handle<JSFunction> function(holder);
615
616 // Find the top invocation of the function by traversing frames.
617 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
618 // Skip all frames that aren't invocations of the given function.
619 if (it.frame()->function() != *function) continue;
620 // Once we have found the frame, we need to go to the caller
621 // frame. This may require skipping through a number of top-level
622 // frames, e.g. frames for scripts not functions.
623 while (true) {
624 it.Advance();
625 if (it.done()) return Heap::null_value();
626 JSFunction* caller = JSFunction::cast(it.frame()->function());
627 if (!caller->shared()->is_toplevel()) return caller;
628 }
629 }
630
631 // No frame corresponding to the given function found. Return null.
632 return Heap::null_value();
633}
634
635
636const AccessorDescriptor Accessors::FunctionCaller = {
637 FunctionGetCaller,
638 ReadOnlySetAccessor,
639 0
640};
641
642
643//
644// Accessors::ObjectPrototype
645//
646
647
John Reck59135872010-11-02 12:39:01 -0700648MaybeObject* Accessors::ObjectGetPrototype(Object* receiver, void*) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 Object* current = receiver->GetPrototype();
650 while (current->IsJSObject() &&
651 JSObject::cast(current)->map()->is_hidden_prototype()) {
652 current = current->GetPrototype();
653 }
654 return current;
655}
656
657
John Reck59135872010-11-02 12:39:01 -0700658MaybeObject* Accessors::ObjectSetPrototype(JSObject* receiver,
659 Object* value,
660 void*) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000661 const bool skip_hidden_prototypes = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000662 // To be consistent with other Set functions, return the value.
Andrei Popescu402d9372010-02-26 13:31:12 +0000663 return receiver->SetPrototype(value, skip_hidden_prototypes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000664}
665
666
667const AccessorDescriptor Accessors::ObjectPrototype = {
668 ObjectGetPrototype,
669 ObjectSetPrototype,
670 0
671};
672
673} } // namespace v8::internal