blob: a4c38b72c248be34fdf0be53056438aae663c9e6 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 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 "api.h"
31#include "arguments.h"
32#include "bootstrapper.h"
33#include "compiler.h"
34#include "debug.h"
35#include "execution.h"
36#include "global-handles.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "messages.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010039#include "profile-generator-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "serialize.h"
41#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010042#include "top.h"
Steve Blockd0582a62009-12-15 09:54:21 +000043#include "utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044#include "v8threads.h"
45#include "version.h"
46
Steve Block6ded16b2010-05-10 14:33:55 +010047#include "../include/v8-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000048
49#define LOG_API(expr) LOG(ApiEntryCall(expr))
50
51#ifdef ENABLE_HEAP_PROTECTION
52#define ENTER_V8 i::VMState __state__(i::OTHER)
53#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
54#else
55#define ENTER_V8 ((void) 0)
56#define LEAVE_V8 ((void) 0)
57#endif
58
59namespace v8 {
60
61
62#define ON_BAILOUT(location, code) \
63 if (IsDeadCheck(location)) { \
64 code; \
65 UNREACHABLE(); \
66 }
67
68
69#define EXCEPTION_PREAMBLE() \
70 thread_local.IncrementCallDepth(); \
71 ASSERT(!i::Top::external_caught_exception()); \
72 bool has_pending_exception = false
73
74
75#define EXCEPTION_BAILOUT_CHECK(value) \
76 do { \
77 thread_local.DecrementCallDepth(); \
78 if (has_pending_exception) { \
79 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
80 if (!thread_local.ignore_out_of_memory()) \
81 i::V8::FatalProcessOutOfMemory(NULL); \
82 } \
83 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
84 i::Top::OptionalRescheduleException(call_depth_is_zero); \
85 return value; \
86 } \
87 } while (false)
88
89
90#define API_ENTRY_CHECK(msg) \
91 do { \
92 if (v8::Locker::IsActive()) { \
93 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
94 msg, \
95 "Entering the V8 API without proper locking in place"); \
96 } \
97 } while (false)
98
99// --- D a t a t h a t i s s p e c i f i c t o a t h r e a d ---
100
101
102static i::HandleScopeImplementer thread_local;
103
104
105// --- E x c e p t i o n B e h a v i o r ---
106
107
108static FatalErrorCallback exception_behavior = NULL;
109int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
110int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
111int i::Internals::kProxyType = PROXY_TYPE;
112
113static void DefaultFatalErrorHandler(const char* location,
114 const char* message) {
115 ENTER_V8;
116 API_Fatal(location, message);
117}
118
119
120
121static FatalErrorCallback& GetFatalErrorHandler() {
122 if (exception_behavior == NULL) {
123 exception_behavior = DefaultFatalErrorHandler;
124 }
125 return exception_behavior;
126}
127
128
129
130// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
131// The default fatal error handler is called and execution is stopped.
132void i::V8::FatalProcessOutOfMemory(const char* location) {
Steve Blockd0582a62009-12-15 09:54:21 +0000133 i::HeapStats heap_stats;
134 int start_marker;
135 heap_stats.start_marker = &start_marker;
136 int new_space_size;
137 heap_stats.new_space_size = &new_space_size;
138 int new_space_capacity;
139 heap_stats.new_space_capacity = &new_space_capacity;
140 int old_pointer_space_size;
141 heap_stats.old_pointer_space_size = &old_pointer_space_size;
142 int old_pointer_space_capacity;
143 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
144 int old_data_space_size;
145 heap_stats.old_data_space_size = &old_data_space_size;
146 int old_data_space_capacity;
147 heap_stats.old_data_space_capacity = &old_data_space_capacity;
148 int code_space_size;
149 heap_stats.code_space_size = &code_space_size;
150 int code_space_capacity;
151 heap_stats.code_space_capacity = &code_space_capacity;
152 int map_space_size;
153 heap_stats.map_space_size = &map_space_size;
154 int map_space_capacity;
155 heap_stats.map_space_capacity = &map_space_capacity;
156 int cell_space_size;
157 heap_stats.cell_space_size = &cell_space_size;
158 int cell_space_capacity;
159 heap_stats.cell_space_capacity = &cell_space_capacity;
160 int lo_space_size;
161 heap_stats.lo_space_size = &lo_space_size;
162 int global_handle_count;
163 heap_stats.global_handle_count = &global_handle_count;
164 int weak_global_handle_count;
165 heap_stats.weak_global_handle_count = &weak_global_handle_count;
166 int pending_global_handle_count;
167 heap_stats.pending_global_handle_count = &pending_global_handle_count;
168 int near_death_global_handle_count;
169 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
170 int destroyed_global_handle_count;
171 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
172 int end_marker;
173 heap_stats.end_marker = &end_marker;
174 i::Heap::RecordStats(&heap_stats);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 i::V8::SetFatalError();
176 FatalErrorCallback callback = GetFatalErrorHandler();
177 {
178 LEAVE_V8;
179 callback(location, "Allocation failed - process out of memory");
180 }
181 // If the callback returns, we stop execution.
182 UNREACHABLE();
183}
184
185
186void V8::SetFatalErrorHandler(FatalErrorCallback that) {
187 exception_behavior = that;
188}
189
190
191bool Utils::ReportApiFailure(const char* location, const char* message) {
192 FatalErrorCallback callback = GetFatalErrorHandler();
193 callback(location, message);
194 i::V8::SetFatalError();
195 return false;
196}
197
198
199bool V8::IsDead() {
200 return i::V8::IsDead();
201}
202
203
204static inline bool ApiCheck(bool condition,
205 const char* location,
206 const char* message) {
207 return condition ? true : Utils::ReportApiFailure(location, message);
208}
209
210
211static bool ReportV8Dead(const char* location) {
212 FatalErrorCallback callback = GetFatalErrorHandler();
213 callback(location, "V8 is no longer usable");
214 return true;
215}
216
217
218static bool ReportEmptyHandle(const char* location) {
219 FatalErrorCallback callback = GetFatalErrorHandler();
220 callback(location, "Reading from empty handle");
221 return true;
222}
223
224
225/**
226 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
227 * out of memory at some point this check will fail. It should be called on
228 * entry to all methods that touch anything in the heap, except destructors
229 * which you sometimes can't avoid calling after the vm has crashed. Functions
230 * that call EnsureInitialized or ON_BAILOUT don't have to also call
231 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
232 * can arrange to return if the VM is dead. This is needed to ensure that no VM
233 * heap allocations are attempted on a dead VM. EnsureInitialized has the
234 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
235 * yet been done.
236 */
237static inline bool IsDeadCheck(const char* location) {
238 return !i::V8::IsRunning()
239 && i::V8::IsDead() ? ReportV8Dead(location) : false;
240}
241
242
243static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
244 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
245}
246
247
248static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
249 return (obj == 0) ? ReportEmptyHandle(location) : false;
250}
251
252// --- S t a t i c s ---
253
254
255static i::StringInputBuffer write_input_buffer;
256
257
258static inline bool EnsureInitialized(const char* location) {
259 if (i::V8::IsRunning()) {
260 return true;
261 }
262 if (IsDeadCheck(location)) {
263 return false;
264 }
265 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
266}
267
268
269ImplementationUtilities::HandleScopeData*
270 ImplementationUtilities::CurrentHandleScope() {
271 return &i::HandleScope::current_;
272}
273
274
275#ifdef DEBUG
276void ImplementationUtilities::ZapHandleRange(i::Object** begin,
277 i::Object** end) {
278 i::HandleScope::ZapRange(begin, end);
279}
280#endif
281
282
283v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
284 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
285 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
286}
287
288
289v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
290 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
291 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
292}
293
294
295v8::Handle<v8::Boolean> ImplementationUtilities::True() {
296 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
297 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
298}
299
300
301v8::Handle<v8::Boolean> ImplementationUtilities::False() {
302 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
303 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
304}
305
306
307void V8::SetFlagsFromString(const char* str, int length) {
308 i::FlagList::SetFlagsFromString(str, length);
309}
310
311
312void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
313 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
314}
315
316
317v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
318 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
319 ENTER_V8;
320 // If we're passed an empty handle, we throw an undefined exception
321 // to deal more gracefully with out of memory situations.
322 if (value.IsEmpty()) {
323 i::Top::ScheduleThrow(i::Heap::undefined_value());
324 } else {
325 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
326 }
327 return v8::Undefined();
328}
329
330
331RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
332
333
334RegisteredExtension::RegisteredExtension(Extension* extension)
335 : extension_(extension), state_(UNVISITED) { }
336
337
338void RegisteredExtension::Register(RegisteredExtension* that) {
339 that->next_ = RegisteredExtension::first_extension_;
340 RegisteredExtension::first_extension_ = that;
341}
342
343
344void RegisterExtension(Extension* that) {
345 RegisteredExtension* extension = new RegisteredExtension(that);
346 RegisteredExtension::Register(extension);
347}
348
349
350Extension::Extension(const char* name,
351 const char* source,
352 int dep_count,
353 const char** deps)
354 : name_(name),
355 source_(source),
356 dep_count_(dep_count),
357 deps_(deps),
358 auto_enable_(false) { }
359
360
361v8::Handle<Primitive> Undefined() {
362 LOG_API("Undefined");
363 return ImplementationUtilities::Undefined();
364}
365
366
367v8::Handle<Primitive> Null() {
368 LOG_API("Null");
369 return ImplementationUtilities::Null();
370}
371
372
373v8::Handle<Boolean> True() {
374 LOG_API("True");
375 return ImplementationUtilities::True();
376}
377
378
379v8::Handle<Boolean> False() {
380 LOG_API("False");
381 return ImplementationUtilities::False();
382}
383
384
385ResourceConstraints::ResourceConstraints()
386 : max_young_space_size_(0),
387 max_old_space_size_(0),
388 stack_limit_(NULL) { }
389
390
391bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000392 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000394 if (young_space_size != 0 || old_gen_size != 0) {
395 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 if (!result) return false;
397 }
398 if (constraints->stack_limit() != NULL) {
399 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
400 i::StackGuard::SetStackLimit(limit);
401 }
402 return true;
403}
404
405
406i::Object** V8::GlobalizeReference(i::Object** obj) {
407 if (IsDeadCheck("V8::Persistent::New")) return NULL;
408 LOG_API("Persistent::New");
409 i::Handle<i::Object> result =
410 i::GlobalHandles::Create(*obj);
411 return result.location();
412}
413
414
415void V8::MakeWeak(i::Object** object, void* parameters,
416 WeakReferenceCallback callback) {
417 LOG_API("MakeWeak");
418 i::GlobalHandles::MakeWeak(object, parameters, callback);
419}
420
421
422void V8::ClearWeak(i::Object** obj) {
423 LOG_API("ClearWeak");
424 i::GlobalHandles::ClearWeakness(obj);
425}
426
427
428bool V8::IsGlobalNearDeath(i::Object** obj) {
429 LOG_API("IsGlobalNearDeath");
430 if (!i::V8::IsRunning()) return false;
431 return i::GlobalHandles::IsNearDeath(obj);
432}
433
434
435bool V8::IsGlobalWeak(i::Object** obj) {
436 LOG_API("IsGlobalWeak");
437 if (!i::V8::IsRunning()) return false;
438 return i::GlobalHandles::IsWeak(obj);
439}
440
441
442void V8::DisposeGlobal(i::Object** obj) {
443 LOG_API("DisposeGlobal");
444 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000445 i::GlobalHandles::Destroy(obj);
446}
447
448// --- H a n d l e s ---
449
450
451HandleScope::HandleScope() : is_closed_(false) {
452 API_ENTRY_CHECK("HandleScope::HandleScope");
453 i::HandleScope::Enter(&previous_);
454}
455
456
457HandleScope::~HandleScope() {
458 if (!is_closed_) {
459 i::HandleScope::Leave(&previous_);
460 }
461}
462
463
464int HandleScope::NumberOfHandles() {
465 return i::HandleScope::NumberOfHandles();
466}
467
468
469i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
470 return i::HandleScope::CreateHandle(value);
471}
472
473
474void Context::Enter() {
475 if (IsDeadCheck("v8::Context::Enter()")) return;
476 ENTER_V8;
477 i::Handle<i::Context> env = Utils::OpenHandle(this);
478 thread_local.EnterContext(env);
479
480 thread_local.SaveContext(i::Top::context());
481 i::Top::set_context(*env);
482}
483
484
485void Context::Exit() {
486 if (!i::V8::IsRunning()) return;
487 if (!ApiCheck(thread_local.LeaveLastContext(),
488 "v8::Context::Exit()",
489 "Cannot exit non-entered context")) {
490 return;
491 }
492
493 // Content of 'last_context' could be NULL.
494 i::Context* last_context = thread_local.RestoreContext();
495 i::Top::set_context(last_context);
496}
497
498
Steve Blockd0582a62009-12-15 09:54:21 +0000499void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 if (IsDeadCheck("v8::Context::SetData()")) return;
501 ENTER_V8;
502 {
503 HandleScope scope;
504 i::Handle<i::Context> env = Utils::OpenHandle(this);
505 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
506 ASSERT(env->IsGlobalContext());
507 if (env->IsGlobalContext()) {
508 env->set_data(*raw_data);
509 }
510 }
511}
512
513
514v8::Local<v8::Value> Context::GetData() {
515 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
516 ENTER_V8;
517 i::Object* raw_result = NULL;
518 {
519 HandleScope scope;
520 i::Handle<i::Context> env = Utils::OpenHandle(this);
521 ASSERT(env->IsGlobalContext());
522 if (env->IsGlobalContext()) {
523 raw_result = env->data();
524 } else {
525 return Local<Value>();
526 }
527 }
528 i::Handle<i::Object> result(raw_result);
529 return Utils::ToLocal(result);
530}
531
532
533i::Object** v8::HandleScope::RawClose(i::Object** value) {
534 if (!ApiCheck(!is_closed_,
535 "v8::HandleScope::Close()",
536 "Local scope has already been closed")) {
537 return 0;
538 }
539 LOG_API("CloseHandleScope");
540
541 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100542 i::Object* result = NULL;
543 if (value != NULL) {
544 result = *value;
545 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000546 is_closed_ = true;
547 i::HandleScope::Leave(&previous_);
548
Steve Block6ded16b2010-05-10 14:33:55 +0100549 if (value == NULL) {
550 return NULL;
551 }
552
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 // Allocate a new handle on the previous handle block.
554 i::Handle<i::Object> handle(result);
555 return handle.location();
556}
557
558
559// --- N e a n d e r ---
560
561
562// A constructor cannot easily return an error value, therefore it is necessary
563// to check for a dead VM with ON_BAILOUT before constructing any Neander
564// objects. To remind you about this there is no HandleScope in the
565// NeanderObject constructor. When you add one to the site calling the
566// constructor you should check that you ensured the VM was not dead first.
567NeanderObject::NeanderObject(int size) {
568 EnsureInitialized("v8::Nowhere");
569 ENTER_V8;
570 value_ = i::Factory::NewNeanderObject();
571 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
572 value_->set_elements(*elements);
573}
574
575
576int NeanderObject::size() {
577 return i::FixedArray::cast(value_->elements())->length();
578}
579
580
581NeanderArray::NeanderArray() : obj_(2) {
582 obj_.set(0, i::Smi::FromInt(0));
583}
584
585
586int NeanderArray::length() {
587 return i::Smi::cast(obj_.get(0))->value();
588}
589
590
591i::Object* NeanderArray::get(int offset) {
592 ASSERT(0 <= offset);
593 ASSERT(offset < length());
594 return obj_.get(offset + 1);
595}
596
597
598// This method cannot easily return an error value, therefore it is necessary
599// to check for a dead VM with ON_BAILOUT before calling it. To remind you
600// about this there is no HandleScope in this method. When you add one to the
601// site calling this method you should check that you ensured the VM was not
602// dead first.
603void NeanderArray::add(i::Handle<i::Object> value) {
604 int length = this->length();
605 int size = obj_.size();
606 if (length == size - 1) {
607 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
608 for (int i = 0; i < length; i++)
609 new_elms->set(i + 1, get(i));
610 obj_.value()->set_elements(*new_elms);
611 }
612 obj_.set(length + 1, *value);
613 obj_.set(0, i::Smi::FromInt(length + 1));
614}
615
616
617void NeanderArray::set(int index, i::Object* value) {
618 if (index < 0 || index >= this->length()) return;
619 obj_.set(index + 1, value);
620}
621
622
623// --- T e m p l a t e ---
624
625
626static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
627 that->set_tag(i::Smi::FromInt(type));
628}
629
630
631void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
632 v8::PropertyAttribute attribute) {
633 if (IsDeadCheck("v8::Template::SetProperty()")) return;
634 ENTER_V8;
635 HandleScope scope;
636 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
637 if (list->IsUndefined()) {
638 list = NeanderArray().value();
639 Utils::OpenHandle(this)->set_property_list(*list);
640 }
641 NeanderArray array(list);
642 array.add(Utils::OpenHandle(*name));
643 array.add(Utils::OpenHandle(*value));
644 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
645}
646
647
648// --- F u n c t i o n T e m p l a t e ---
649static void InitializeFunctionTemplate(
650 i::Handle<i::FunctionTemplateInfo> info) {
651 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
652 info->set_flag(0);
653}
654
655
656Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
657 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
658 return Local<ObjectTemplate>();
659 }
660 ENTER_V8;
661 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
662 if (result->IsUndefined()) {
663 result = Utils::OpenHandle(*ObjectTemplate::New());
664 Utils::OpenHandle(this)->set_prototype_template(*result);
665 }
666 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
667}
668
669
670void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
671 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
672 ENTER_V8;
673 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
674}
675
676
677// To distinguish the function templates, so that we can find them in the
678// function cache of the global context.
679static int next_serial_number = 0;
680
681
682Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
683 v8::Handle<Value> data, v8::Handle<Signature> signature) {
684 EnsureInitialized("v8::FunctionTemplate::New()");
685 LOG_API("FunctionTemplate::New");
686 ENTER_V8;
687 i::Handle<i::Struct> struct_obj =
688 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
689 i::Handle<i::FunctionTemplateInfo> obj =
690 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
691 InitializeFunctionTemplate(obj);
692 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
693 if (callback != 0) {
694 if (data.IsEmpty()) data = v8::Undefined();
695 Utils::ToLocal(obj)->SetCallHandler(callback, data);
696 }
697 obj->set_undetectable(false);
698 obj->set_needs_access_check(false);
699
700 if (!signature.IsEmpty())
701 obj->set_signature(*Utils::OpenHandle(*signature));
702 return Utils::ToLocal(obj);
703}
704
705
706Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
707 int argc, Handle<FunctionTemplate> argv[]) {
708 EnsureInitialized("v8::Signature::New()");
709 LOG_API("Signature::New");
710 ENTER_V8;
711 i::Handle<i::Struct> struct_obj =
712 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
713 i::Handle<i::SignatureInfo> obj =
714 i::Handle<i::SignatureInfo>::cast(struct_obj);
715 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
716 if (argc > 0) {
717 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
718 for (int i = 0; i < argc; i++) {
719 if (!argv[i].IsEmpty())
720 args->set(i, *Utils::OpenHandle(*argv[i]));
721 }
722 obj->set_args(*args);
723 }
724 return Utils::ToLocal(obj);
725}
726
727
728Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
729 Handle<FunctionTemplate> types[1] = { type };
730 return TypeSwitch::New(1, types);
731}
732
733
734Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
735 EnsureInitialized("v8::TypeSwitch::New()");
736 LOG_API("TypeSwitch::New");
737 ENTER_V8;
738 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
739 for (int i = 0; i < argc; i++)
740 vector->set(i, *Utils::OpenHandle(*types[i]));
741 i::Handle<i::Struct> struct_obj =
742 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
743 i::Handle<i::TypeSwitchInfo> obj =
744 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
745 obj->set_types(*vector);
746 return Utils::ToLocal(obj);
747}
748
749
750int TypeSwitch::match(v8::Handle<Value> value) {
751 LOG_API("TypeSwitch::match");
752 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
753 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
754 i::FixedArray* types = i::FixedArray::cast(info->types());
755 for (int i = 0; i < types->length(); i++) {
756 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
757 return i + 1;
758 }
759 return 0;
760}
761
762
763void FunctionTemplate::SetCallHandler(InvocationCallback callback,
764 v8::Handle<Value> data) {
765 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
766 ENTER_V8;
767 HandleScope scope;
768 i::Handle<i::Struct> struct_obj =
769 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
770 i::Handle<i::CallHandlerInfo> obj =
771 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
772 obj->set_callback(*FromCData(callback));
773 if (data.IsEmpty()) data = v8::Undefined();
774 obj->set_data(*Utils::OpenHandle(*data));
775 Utils::OpenHandle(this)->set_call_code(*obj);
776}
777
778
779void FunctionTemplate::AddInstancePropertyAccessor(
780 v8::Handle<String> name,
781 AccessorGetter getter,
782 AccessorSetter setter,
783 v8::Handle<Value> data,
784 v8::AccessControl settings,
785 v8::PropertyAttribute attributes) {
786 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
787 return;
788 }
789 ENTER_V8;
790 HandleScope scope;
791 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
792 ASSERT(getter != NULL);
793 obj->set_getter(*FromCData(getter));
794 obj->set_setter(*FromCData(setter));
795 if (data.IsEmpty()) data = v8::Undefined();
796 obj->set_data(*Utils::OpenHandle(*data));
797 obj->set_name(*Utils::OpenHandle(*name));
798 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
799 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
800 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
801 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
802
803 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
804 if (list->IsUndefined()) {
805 list = NeanderArray().value();
806 Utils::OpenHandle(this)->set_property_accessors(*list);
807 }
808 NeanderArray array(list);
809 array.add(obj);
810}
811
812
813Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
814 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
815 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
816 return Local<ObjectTemplate>();
817 ENTER_V8;
818 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
819 Local<ObjectTemplate> templ =
820 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
821 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
822 }
823 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
824 Utils::OpenHandle(this)->instance_template()));
825 return Utils::ToLocal(result);
826}
827
828
829void FunctionTemplate::SetClassName(Handle<String> name) {
830 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
831 ENTER_V8;
832 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
833}
834
835
836void FunctionTemplate::SetHiddenPrototype(bool value) {
837 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
838 ENTER_V8;
839 Utils::OpenHandle(this)->set_hidden_prototype(value);
840}
841
842
843void FunctionTemplate::SetNamedInstancePropertyHandler(
844 NamedPropertyGetter getter,
845 NamedPropertySetter setter,
846 NamedPropertyQuery query,
847 NamedPropertyDeleter remover,
848 NamedPropertyEnumerator enumerator,
849 Handle<Value> data) {
850 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
851 return;
852 }
853 ENTER_V8;
854 HandleScope scope;
855 i::Handle<i::Struct> struct_obj =
856 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
857 i::Handle<i::InterceptorInfo> obj =
858 i::Handle<i::InterceptorInfo>::cast(struct_obj);
859 if (getter != 0) obj->set_getter(*FromCData(getter));
860 if (setter != 0) obj->set_setter(*FromCData(setter));
861 if (query != 0) obj->set_query(*FromCData(query));
862 if (remover != 0) obj->set_deleter(*FromCData(remover));
863 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
864 if (data.IsEmpty()) data = v8::Undefined();
865 obj->set_data(*Utils::OpenHandle(*data));
866 Utils::OpenHandle(this)->set_named_property_handler(*obj);
867}
868
869
870void FunctionTemplate::SetIndexedInstancePropertyHandler(
871 IndexedPropertyGetter getter,
872 IndexedPropertySetter setter,
873 IndexedPropertyQuery query,
874 IndexedPropertyDeleter remover,
875 IndexedPropertyEnumerator enumerator,
876 Handle<Value> data) {
877 if (IsDeadCheck(
878 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
879 return;
880 }
881 ENTER_V8;
882 HandleScope scope;
883 i::Handle<i::Struct> struct_obj =
884 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
885 i::Handle<i::InterceptorInfo> obj =
886 i::Handle<i::InterceptorInfo>::cast(struct_obj);
887 if (getter != 0) obj->set_getter(*FromCData(getter));
888 if (setter != 0) obj->set_setter(*FromCData(setter));
889 if (query != 0) obj->set_query(*FromCData(query));
890 if (remover != 0) obj->set_deleter(*FromCData(remover));
891 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
892 if (data.IsEmpty()) data = v8::Undefined();
893 obj->set_data(*Utils::OpenHandle(*data));
894 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
895}
896
897
898void FunctionTemplate::SetInstanceCallAsFunctionHandler(
899 InvocationCallback callback,
900 Handle<Value> data) {
901 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
902 return;
903 }
904 ENTER_V8;
905 HandleScope scope;
906 i::Handle<i::Struct> struct_obj =
907 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
908 i::Handle<i::CallHandlerInfo> obj =
909 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
910 obj->set_callback(*FromCData(callback));
911 if (data.IsEmpty()) data = v8::Undefined();
912 obj->set_data(*Utils::OpenHandle(*data));
913 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
914}
915
916
917// --- O b j e c t T e m p l a t e ---
918
919
920Local<ObjectTemplate> ObjectTemplate::New() {
921 return New(Local<FunctionTemplate>());
922}
923
924
925Local<ObjectTemplate> ObjectTemplate::New(
926 v8::Handle<FunctionTemplate> constructor) {
927 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
928 EnsureInitialized("v8::ObjectTemplate::New()");
929 LOG_API("ObjectTemplate::New");
930 ENTER_V8;
931 i::Handle<i::Struct> struct_obj =
932 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
933 i::Handle<i::ObjectTemplateInfo> obj =
934 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
935 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
936 if (!constructor.IsEmpty())
937 obj->set_constructor(*Utils::OpenHandle(*constructor));
938 obj->set_internal_field_count(i::Smi::FromInt(0));
939 return Utils::ToLocal(obj);
940}
941
942
943// Ensure that the object template has a constructor. If no
944// constructor is available we create one.
945static void EnsureConstructor(ObjectTemplate* object_template) {
946 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
947 Local<FunctionTemplate> templ = FunctionTemplate::New();
948 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
949 constructor->set_instance_template(*Utils::OpenHandle(object_template));
950 Utils::OpenHandle(object_template)->set_constructor(*constructor);
951 }
952}
953
954
955void ObjectTemplate::SetAccessor(v8::Handle<String> name,
956 AccessorGetter getter,
957 AccessorSetter setter,
958 v8::Handle<Value> data,
959 AccessControl settings,
960 PropertyAttribute attribute) {
961 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
962 ENTER_V8;
963 HandleScope scope;
964 EnsureConstructor(this);
965 i::FunctionTemplateInfo* constructor =
966 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
967 i::Handle<i::FunctionTemplateInfo> cons(constructor);
968 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
969 getter,
970 setter,
971 data,
972 settings,
973 attribute);
974}
975
976
977void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
978 NamedPropertySetter setter,
979 NamedPropertyQuery query,
980 NamedPropertyDeleter remover,
981 NamedPropertyEnumerator enumerator,
982 Handle<Value> data) {
983 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
984 ENTER_V8;
985 HandleScope scope;
986 EnsureConstructor(this);
987 i::FunctionTemplateInfo* constructor =
988 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
989 i::Handle<i::FunctionTemplateInfo> cons(constructor);
990 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
991 setter,
992 query,
993 remover,
994 enumerator,
995 data);
996}
997
998
999void ObjectTemplate::MarkAsUndetectable() {
1000 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1001 ENTER_V8;
1002 HandleScope scope;
1003 EnsureConstructor(this);
1004 i::FunctionTemplateInfo* constructor =
1005 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1006 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1007 cons->set_undetectable(true);
1008}
1009
1010
1011void ObjectTemplate::SetAccessCheckCallbacks(
1012 NamedSecurityCallback named_callback,
1013 IndexedSecurityCallback indexed_callback,
1014 Handle<Value> data,
1015 bool turned_on_by_default) {
1016 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1017 ENTER_V8;
1018 HandleScope scope;
1019 EnsureConstructor(this);
1020
1021 i::Handle<i::Struct> struct_info =
1022 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1023 i::Handle<i::AccessCheckInfo> info =
1024 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1025 info->set_named_callback(*FromCData(named_callback));
1026 info->set_indexed_callback(*FromCData(indexed_callback));
1027 if (data.IsEmpty()) data = v8::Undefined();
1028 info->set_data(*Utils::OpenHandle(*data));
1029
1030 i::FunctionTemplateInfo* constructor =
1031 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1032 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1033 cons->set_access_check_info(*info);
1034 cons->set_needs_access_check(turned_on_by_default);
1035}
1036
1037
1038void ObjectTemplate::SetIndexedPropertyHandler(
1039 IndexedPropertyGetter getter,
1040 IndexedPropertySetter setter,
1041 IndexedPropertyQuery query,
1042 IndexedPropertyDeleter remover,
1043 IndexedPropertyEnumerator enumerator,
1044 Handle<Value> data) {
1045 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1046 ENTER_V8;
1047 HandleScope scope;
1048 EnsureConstructor(this);
1049 i::FunctionTemplateInfo* constructor =
1050 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1051 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1052 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1053 setter,
1054 query,
1055 remover,
1056 enumerator,
1057 data);
1058}
1059
1060
1061void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1062 Handle<Value> data) {
1063 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1064 ENTER_V8;
1065 HandleScope scope;
1066 EnsureConstructor(this);
1067 i::FunctionTemplateInfo* constructor =
1068 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1069 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1070 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1071}
1072
1073
1074int ObjectTemplate::InternalFieldCount() {
1075 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1076 return 0;
1077 }
1078 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1079}
1080
1081
1082void ObjectTemplate::SetInternalFieldCount(int value) {
1083 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1084 if (!ApiCheck(i::Smi::IsValid(value),
1085 "v8::ObjectTemplate::SetInternalFieldCount()",
1086 "Invalid internal field count")) {
1087 return;
1088 }
1089 ENTER_V8;
1090 if (value > 0) {
1091 // The internal field count is set by the constructor function's
1092 // construct code, so we ensure that there is a constructor
1093 // function to do the setting.
1094 EnsureConstructor(this);
1095 }
1096 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1097}
1098
1099
1100// --- S c r i p t D a t a ---
1101
1102
1103ScriptData* ScriptData::PreCompile(const char* input, int length) {
1104 unibrow::Utf8InputBuffer<> buf(input, length);
1105 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1106}
1107
1108
1109ScriptData* ScriptData::New(unsigned* data, int length) {
1110 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1111}
1112
1113
1114// --- S c r i p t ---
1115
1116
1117Local<Script> Script::New(v8::Handle<String> source,
1118 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001119 v8::ScriptData* pre_data,
1120 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001121 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1122 LOG_API("Script::New");
1123 ENTER_V8;
1124 i::Handle<i::String> str = Utils::OpenHandle(*source);
1125 i::Handle<i::Object> name_obj;
1126 int line_offset = 0;
1127 int column_offset = 0;
1128 if (origin != NULL) {
1129 if (!origin->ResourceName().IsEmpty()) {
1130 name_obj = Utils::OpenHandle(*origin->ResourceName());
1131 }
1132 if (!origin->ResourceLineOffset().IsEmpty()) {
1133 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1134 }
1135 if (!origin->ResourceColumnOffset().IsEmpty()) {
1136 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1137 }
1138 }
1139 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001140 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001141 // We assert that the pre-data is sane, even though we can actually
1142 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001143 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001144 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001145 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1146 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001147 }
Steve Block6ded16b2010-05-10 14:33:55 +01001148 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001149 i::Compiler::Compile(str,
1150 name_obj,
1151 line_offset,
1152 column_offset,
1153 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001154 pre_data_impl,
1155 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001156 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001157 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001158 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001159 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001160}
1161
1162
1163Local<Script> Script::New(v8::Handle<String> source,
1164 v8::Handle<Value> file_name) {
1165 ScriptOrigin origin(file_name);
1166 return New(source, &origin);
1167}
1168
1169
1170Local<Script> Script::Compile(v8::Handle<String> source,
1171 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001172 v8::ScriptData* pre_data,
1173 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001174 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1175 LOG_API("Script::Compile");
1176 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001177 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 if (generic.IsEmpty())
1179 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001180 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1181 i::Handle<i::SharedFunctionInfo> function =
1182 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001183 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001184 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1185 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001186 return Local<Script>(ToApi<Script>(result));
1187}
1188
1189
1190Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001191 v8::Handle<Value> file_name,
1192 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001193 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001194 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001195}
1196
1197
1198Local<Value> Script::Run() {
1199 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1200 LOG_API("Script::Run");
1201 ENTER_V8;
1202 i::Object* raw_result = NULL;
1203 {
1204 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001205 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1206 i::Handle<i::JSFunction> fun;
1207 if (obj->IsSharedFunctionInfo()) {
1208 i::Handle<i::SharedFunctionInfo>
1209 function_info(i::SharedFunctionInfo::cast(*obj));
1210 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1211 function_info, i::Top::global_context());
1212 } else {
1213 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 }
1215 EXCEPTION_PREAMBLE();
1216 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1217 i::Handle<i::Object> result =
1218 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1219 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1220 raw_result = *result;
1221 }
1222 i::Handle<i::Object> result(raw_result);
1223 return Utils::ToLocal(result);
1224}
1225
1226
Steve Block6ded16b2010-05-10 14:33:55 +01001227static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1228 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1229 i::Handle<i::SharedFunctionInfo> result;
1230 if (obj->IsSharedFunctionInfo()) {
1231 result =
1232 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1233 } else {
1234 result =
1235 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1236 }
1237 return result;
1238}
1239
1240
Steve Blocka7e24c12009-10-30 11:49:00 +00001241Local<Value> Script::Id() {
1242 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1243 LOG_API("Script::Id");
1244 i::Object* raw_id = NULL;
1245 {
1246 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001247 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1248 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001249 i::Handle<i::Object> id(script->id());
1250 raw_id = *id;
1251 }
1252 i::Handle<i::Object> id(raw_id);
1253 return Utils::ToLocal(id);
1254}
1255
1256
Steve Blockd0582a62009-12-15 09:54:21 +00001257void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001258 ON_BAILOUT("v8::Script::SetData()", return);
1259 LOG_API("Script::SetData");
1260 {
1261 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001262 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001263 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001264 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001265 script->set_data(*raw_data);
1266 }
1267}
1268
1269
1270// --- E x c e p t i o n s ---
1271
1272
1273v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001274 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001275 exception_(i::Heap::the_hole_value()),
1276 message_(i::Smi::FromInt(0)),
1277 is_verbose_(false),
1278 can_continue_(true),
1279 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001280 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 i::Top::RegisterTryCatchHandler(this);
1282}
1283
1284
1285v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001286 if (rethrow_) {
1287 v8::HandleScope scope;
1288 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1289 i::Top::UnregisterTryCatchHandler(this);
1290 v8::ThrowException(exc);
1291 } else {
1292 i::Top::UnregisterTryCatchHandler(this);
1293 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001294}
1295
1296
1297bool v8::TryCatch::HasCaught() const {
1298 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1299}
1300
1301
1302bool v8::TryCatch::CanContinue() const {
1303 return can_continue_;
1304}
1305
1306
Steve Blockd0582a62009-12-15 09:54:21 +00001307v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1308 if (!HasCaught()) return v8::Local<v8::Value>();
1309 rethrow_ = true;
1310 return v8::Undefined();
1311}
1312
1313
Steve Blocka7e24c12009-10-30 11:49:00 +00001314v8::Local<Value> v8::TryCatch::Exception() const {
1315 if (HasCaught()) {
1316 // Check for out of memory exception.
1317 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1318 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1319 } else {
1320 return v8::Local<Value>();
1321 }
1322}
1323
1324
1325v8::Local<Value> v8::TryCatch::StackTrace() const {
1326 if (HasCaught()) {
1327 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1328 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1329 v8::HandleScope scope;
1330 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1331 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1332 if (!obj->HasProperty(*name))
1333 return v8::Local<Value>();
1334 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1335 } else {
1336 return v8::Local<Value>();
1337 }
1338}
1339
1340
1341v8::Local<v8::Message> v8::TryCatch::Message() const {
1342 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1343 i::Object* message = reinterpret_cast<i::Object*>(message_);
1344 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1345 } else {
1346 return v8::Local<v8::Message>();
1347 }
1348}
1349
1350
1351void v8::TryCatch::Reset() {
1352 exception_ = i::Heap::the_hole_value();
1353 message_ = i::Smi::FromInt(0);
1354}
1355
1356
1357void v8::TryCatch::SetVerbose(bool value) {
1358 is_verbose_ = value;
1359}
1360
1361
1362void v8::TryCatch::SetCaptureMessage(bool value) {
1363 capture_message_ = value;
1364}
1365
1366
1367// --- M e s s a g e ---
1368
1369
1370Local<String> Message::Get() const {
1371 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1372 ENTER_V8;
1373 HandleScope scope;
1374 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1375 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1376 Local<String> result = Utils::ToLocal(raw_result);
1377 return scope.Close(result);
1378}
1379
1380
1381v8::Handle<Value> Message::GetScriptResourceName() const {
1382 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1383 return Local<String>();
1384 }
1385 ENTER_V8;
1386 HandleScope scope;
1387 i::Handle<i::JSObject> obj =
1388 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1389 // Return this.script.name.
1390 i::Handle<i::JSValue> script =
1391 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1392 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1393 return scope.Close(Utils::ToLocal(resource_name));
1394}
1395
1396
1397v8::Handle<Value> Message::GetScriptData() const {
1398 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1399 return Local<Value>();
1400 }
1401 ENTER_V8;
1402 HandleScope scope;
1403 i::Handle<i::JSObject> obj =
1404 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1405 // Return this.script.data.
1406 i::Handle<i::JSValue> script =
1407 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1408 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1409 return scope.Close(Utils::ToLocal(data));
1410}
1411
1412
1413static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1414 i::Handle<i::Object> recv,
1415 int argc,
1416 i::Object** argv[],
1417 bool* has_pending_exception) {
1418 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1419 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1420 i::Handle<i::JSFunction> fun =
1421 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1422 i::Handle<i::Object> value =
1423 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1424 return value;
1425}
1426
1427
1428static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1429 i::Handle<i::Object> data,
1430 bool* has_pending_exception) {
1431 i::Object** argv[1] = { data.location() };
1432 return CallV8HeapFunction(name,
1433 i::Top::builtins(),
1434 1,
1435 argv,
1436 has_pending_exception);
1437}
1438
1439
1440int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001441 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001442 ENTER_V8;
1443 HandleScope scope;
1444 EXCEPTION_PREAMBLE();
1445 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1446 Utils::OpenHandle(this),
1447 &has_pending_exception);
1448 EXCEPTION_BAILOUT_CHECK(0);
1449 return static_cast<int>(result->Number());
1450}
1451
1452
1453int Message::GetStartPosition() const {
1454 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1455 ENTER_V8;
1456 HandleScope scope;
1457
1458 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1459 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1460}
1461
1462
1463int Message::GetEndPosition() const {
1464 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1465 ENTER_V8;
1466 HandleScope scope;
1467 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1468 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1469}
1470
1471
1472int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001473 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001474 ENTER_V8;
1475 HandleScope scope;
1476 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1477 EXCEPTION_PREAMBLE();
1478 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1479 "GetPositionInLine",
1480 data_obj,
1481 &has_pending_exception);
1482 EXCEPTION_BAILOUT_CHECK(0);
1483 return static_cast<int>(start_col_obj->Number());
1484}
1485
1486
1487int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001488 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 ENTER_V8;
1490 HandleScope scope;
1491 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1492 EXCEPTION_PREAMBLE();
1493 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1494 "GetPositionInLine",
1495 data_obj,
1496 &has_pending_exception);
1497 EXCEPTION_BAILOUT_CHECK(0);
1498 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1499 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1500 return static_cast<int>(start_col_obj->Number()) + (end - start);
1501}
1502
1503
1504Local<String> Message::GetSourceLine() const {
1505 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1506 ENTER_V8;
1507 HandleScope scope;
1508 EXCEPTION_PREAMBLE();
1509 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1510 Utils::OpenHandle(this),
1511 &has_pending_exception);
1512 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1513 if (result->IsString()) {
1514 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1515 } else {
1516 return Local<String>();
1517 }
1518}
1519
1520
1521void Message::PrintCurrentStackTrace(FILE* out) {
1522 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1523 ENTER_V8;
1524 i::Top::PrintCurrentStackTrace(out);
1525}
1526
1527
Kristian Monsen25f61362010-05-21 11:50:48 +01001528// --- S t a c k T r a c e ---
1529
1530Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1531 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1532 ENTER_V8;
1533 HandleScope scope;
1534 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1535 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1536 return scope.Close(Utils::StackFrameToLocal(obj));
1537}
1538
1539
1540int StackTrace::GetFrameCount() const {
1541 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1542 ENTER_V8;
1543 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1544}
1545
1546
1547Local<Array> StackTrace::AsArray() {
1548 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1549 ENTER_V8;
1550 return Utils::ToLocal(Utils::OpenHandle(this));
1551}
1552
1553
1554Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1555 StackTraceOptions options) {
1556 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1557 ENTER_V8;
1558 return i::Top::CaptureCurrentStackTrace(frame_limit, options);
1559}
1560
1561
1562// --- S t a c k F r a m e ---
1563
1564int StackFrame::GetLineNumber() const {
1565 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1566 return Message::kNoLineNumberInfo;
1567 }
1568 ENTER_V8;
1569 i::HandleScope scope;
1570 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1571 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1572 if (!line->IsSmi()) {
1573 return Message::kNoLineNumberInfo;
1574 }
1575 return i::Smi::cast(*line)->value();
1576}
1577
1578
1579int StackFrame::GetColumn() const {
1580 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1581 return Message::kNoColumnInfo;
1582 }
1583 ENTER_V8;
1584 i::HandleScope scope;
1585 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1586 i::Handle<i::Object> column = GetProperty(self, "column");
1587 if (!column->IsSmi()) {
1588 return Message::kNoColumnInfo;
1589 }
1590 return i::Smi::cast(*column)->value();
1591}
1592
1593
1594Local<String> StackFrame::GetScriptName() const {
1595 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1596 ENTER_V8;
1597 HandleScope scope;
1598 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1599 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1600 if (!name->IsString()) {
1601 return Local<String>();
1602 }
1603 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1604}
1605
1606
1607Local<String> StackFrame::GetFunctionName() const {
1608 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1609 ENTER_V8;
1610 HandleScope scope;
1611 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1612 i::Handle<i::Object> name = GetProperty(self, "functionName");
1613 if (!name->IsString()) {
1614 return Local<String>();
1615 }
1616 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1617}
1618
1619
1620bool StackFrame::IsEval() const {
1621 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1622 ENTER_V8;
1623 i::HandleScope scope;
1624 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1625 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1626 return is_eval->IsTrue();
1627}
1628
1629
1630bool StackFrame::IsConstructor() const {
1631 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1632 ENTER_V8;
1633 i::HandleScope scope;
1634 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1635 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1636 return is_constructor->IsTrue();
1637}
1638
1639
Steve Blocka7e24c12009-10-30 11:49:00 +00001640// --- D a t a ---
1641
1642bool Value::IsUndefined() const {
1643 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1644 return Utils::OpenHandle(this)->IsUndefined();
1645}
1646
1647
1648bool Value::IsNull() const {
1649 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1650 return Utils::OpenHandle(this)->IsNull();
1651}
1652
1653
1654bool Value::IsTrue() const {
1655 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1656 return Utils::OpenHandle(this)->IsTrue();
1657}
1658
1659
1660bool Value::IsFalse() const {
1661 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1662 return Utils::OpenHandle(this)->IsFalse();
1663}
1664
1665
1666bool Value::IsFunction() const {
1667 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1668 return Utils::OpenHandle(this)->IsJSFunction();
1669}
1670
1671
1672bool Value::FullIsString() const {
1673 if (IsDeadCheck("v8::Value::IsString()")) return false;
1674 bool result = Utils::OpenHandle(this)->IsString();
1675 ASSERT_EQ(result, QuickIsString());
1676 return result;
1677}
1678
1679
1680bool Value::IsArray() const {
1681 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1682 return Utils::OpenHandle(this)->IsJSArray();
1683}
1684
1685
1686bool Value::IsObject() const {
1687 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1688 return Utils::OpenHandle(this)->IsJSObject();
1689}
1690
1691
1692bool Value::IsNumber() const {
1693 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1694 return Utils::OpenHandle(this)->IsNumber();
1695}
1696
1697
1698bool Value::IsBoolean() const {
1699 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1700 return Utils::OpenHandle(this)->IsBoolean();
1701}
1702
1703
1704bool Value::IsExternal() const {
1705 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1706 return Utils::OpenHandle(this)->IsProxy();
1707}
1708
1709
1710bool Value::IsInt32() const {
1711 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1712 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1713 if (obj->IsSmi()) return true;
1714 if (obj->IsNumber()) {
1715 double value = obj->Number();
1716 return i::FastI2D(i::FastD2I(value)) == value;
1717 }
1718 return false;
1719}
1720
1721
Steve Block6ded16b2010-05-10 14:33:55 +01001722bool Value::IsUint32() const {
1723 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1724 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1725 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1726 if (obj->IsNumber()) {
1727 double value = obj->Number();
1728 return i::FastUI2D(i::FastD2UI(value)) == value;
1729 }
1730 return false;
1731}
1732
1733
Steve Blocka7e24c12009-10-30 11:49:00 +00001734bool Value::IsDate() const {
1735 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1736 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1737 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1738}
1739
1740
1741Local<String> Value::ToString() const {
1742 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1743 LOG_API("ToString");
1744 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1745 i::Handle<i::Object> str;
1746 if (obj->IsString()) {
1747 str = obj;
1748 } else {
1749 ENTER_V8;
1750 EXCEPTION_PREAMBLE();
1751 str = i::Execution::ToString(obj, &has_pending_exception);
1752 EXCEPTION_BAILOUT_CHECK(Local<String>());
1753 }
1754 return Local<String>(ToApi<String>(str));
1755}
1756
1757
1758Local<String> Value::ToDetailString() const {
1759 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1760 LOG_API("ToDetailString");
1761 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1762 i::Handle<i::Object> str;
1763 if (obj->IsString()) {
1764 str = obj;
1765 } else {
1766 ENTER_V8;
1767 EXCEPTION_PREAMBLE();
1768 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1769 EXCEPTION_BAILOUT_CHECK(Local<String>());
1770 }
1771 return Local<String>(ToApi<String>(str));
1772}
1773
1774
1775Local<v8::Object> Value::ToObject() const {
1776 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1777 LOG_API("ToObject");
1778 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1779 i::Handle<i::Object> val;
1780 if (obj->IsJSObject()) {
1781 val = obj;
1782 } else {
1783 ENTER_V8;
1784 EXCEPTION_PREAMBLE();
1785 val = i::Execution::ToObject(obj, &has_pending_exception);
1786 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1787 }
1788 return Local<v8::Object>(ToApi<Object>(val));
1789}
1790
1791
1792Local<Boolean> Value::ToBoolean() const {
1793 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1794 LOG_API("ToBoolean");
1795 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1796 if (obj->IsBoolean()) {
1797 return Local<Boolean>(ToApi<Boolean>(obj));
1798 } else {
1799 ENTER_V8;
1800 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1801 return Local<Boolean>(ToApi<Boolean>(val));
1802 }
1803}
1804
1805
1806Local<Number> Value::ToNumber() const {
1807 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1808 LOG_API("ToNumber");
1809 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1810 i::Handle<i::Object> num;
1811 if (obj->IsNumber()) {
1812 num = obj;
1813 } else {
1814 ENTER_V8;
1815 EXCEPTION_PREAMBLE();
1816 num = i::Execution::ToNumber(obj, &has_pending_exception);
1817 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1818 }
1819 return Local<Number>(ToApi<Number>(num));
1820}
1821
1822
1823Local<Integer> Value::ToInteger() const {
1824 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1825 LOG_API("ToInteger");
1826 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1827 i::Handle<i::Object> num;
1828 if (obj->IsSmi()) {
1829 num = obj;
1830 } else {
1831 ENTER_V8;
1832 EXCEPTION_PREAMBLE();
1833 num = i::Execution::ToInteger(obj, &has_pending_exception);
1834 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1835 }
1836 return Local<Integer>(ToApi<Integer>(num));
1837}
1838
1839
1840void External::CheckCast(v8::Value* that) {
1841 if (IsDeadCheck("v8::External::Cast()")) return;
1842 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1843 ApiCheck(obj->IsProxy(),
1844 "v8::External::Cast()",
1845 "Could not convert to external");
1846}
1847
1848
1849void v8::Object::CheckCast(Value* that) {
1850 if (IsDeadCheck("v8::Object::Cast()")) return;
1851 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1852 ApiCheck(obj->IsJSObject(),
1853 "v8::Object::Cast()",
1854 "Could not convert to object");
1855}
1856
1857
1858void v8::Function::CheckCast(Value* that) {
1859 if (IsDeadCheck("v8::Function::Cast()")) return;
1860 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1861 ApiCheck(obj->IsJSFunction(),
1862 "v8::Function::Cast()",
1863 "Could not convert to function");
1864}
1865
1866
1867void v8::String::CheckCast(v8::Value* that) {
1868 if (IsDeadCheck("v8::String::Cast()")) return;
1869 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1870 ApiCheck(obj->IsString(),
1871 "v8::String::Cast()",
1872 "Could not convert to string");
1873}
1874
1875
1876void v8::Number::CheckCast(v8::Value* that) {
1877 if (IsDeadCheck("v8::Number::Cast()")) return;
1878 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1879 ApiCheck(obj->IsNumber(),
1880 "v8::Number::Cast()",
1881 "Could not convert to number");
1882}
1883
1884
1885void v8::Integer::CheckCast(v8::Value* that) {
1886 if (IsDeadCheck("v8::Integer::Cast()")) return;
1887 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1888 ApiCheck(obj->IsNumber(),
1889 "v8::Integer::Cast()",
1890 "Could not convert to number");
1891}
1892
1893
1894void v8::Array::CheckCast(Value* that) {
1895 if (IsDeadCheck("v8::Array::Cast()")) return;
1896 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1897 ApiCheck(obj->IsJSArray(),
1898 "v8::Array::Cast()",
1899 "Could not convert to array");
1900}
1901
1902
1903void v8::Date::CheckCast(v8::Value* that) {
1904 if (IsDeadCheck("v8::Date::Cast()")) return;
1905 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1906 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1907 "v8::Date::Cast()",
1908 "Could not convert to date");
1909}
1910
1911
1912bool Value::BooleanValue() const {
1913 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1914 LOG_API("BooleanValue");
1915 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1916 if (obj->IsBoolean()) {
1917 return obj->IsTrue();
1918 } else {
1919 ENTER_V8;
1920 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1921 return value->IsTrue();
1922 }
1923}
1924
1925
1926double Value::NumberValue() const {
1927 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1928 LOG_API("NumberValue");
1929 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1930 i::Handle<i::Object> num;
1931 if (obj->IsNumber()) {
1932 num = obj;
1933 } else {
1934 ENTER_V8;
1935 EXCEPTION_PREAMBLE();
1936 num = i::Execution::ToNumber(obj, &has_pending_exception);
1937 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1938 }
1939 return num->Number();
1940}
1941
1942
1943int64_t Value::IntegerValue() const {
1944 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1945 LOG_API("IntegerValue");
1946 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1947 i::Handle<i::Object> num;
1948 if (obj->IsNumber()) {
1949 num = obj;
1950 } else {
1951 ENTER_V8;
1952 EXCEPTION_PREAMBLE();
1953 num = i::Execution::ToInteger(obj, &has_pending_exception);
1954 EXCEPTION_BAILOUT_CHECK(0);
1955 }
1956 if (num->IsSmi()) {
1957 return i::Smi::cast(*num)->value();
1958 } else {
1959 return static_cast<int64_t>(num->Number());
1960 }
1961}
1962
1963
1964Local<Int32> Value::ToInt32() const {
1965 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1966 LOG_API("ToInt32");
1967 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1968 i::Handle<i::Object> num;
1969 if (obj->IsSmi()) {
1970 num = obj;
1971 } else {
1972 ENTER_V8;
1973 EXCEPTION_PREAMBLE();
1974 num = i::Execution::ToInt32(obj, &has_pending_exception);
1975 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1976 }
1977 return Local<Int32>(ToApi<Int32>(num));
1978}
1979
1980
1981Local<Uint32> Value::ToUint32() const {
1982 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1983 LOG_API("ToUInt32");
1984 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1985 i::Handle<i::Object> num;
1986 if (obj->IsSmi()) {
1987 num = obj;
1988 } else {
1989 ENTER_V8;
1990 EXCEPTION_PREAMBLE();
1991 num = i::Execution::ToUint32(obj, &has_pending_exception);
1992 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1993 }
1994 return Local<Uint32>(ToApi<Uint32>(num));
1995}
1996
1997
1998Local<Uint32> Value::ToArrayIndex() const {
1999 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2000 LOG_API("ToArrayIndex");
2001 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2002 if (obj->IsSmi()) {
2003 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2004 return Local<Uint32>();
2005 }
2006 ENTER_V8;
2007 EXCEPTION_PREAMBLE();
2008 i::Handle<i::Object> string_obj =
2009 i::Execution::ToString(obj, &has_pending_exception);
2010 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2011 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2012 uint32_t index;
2013 if (str->AsArrayIndex(&index)) {
2014 i::Handle<i::Object> value;
2015 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2016 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2017 } else {
2018 value = i::Factory::NewNumber(index);
2019 }
2020 return Utils::Uint32ToLocal(value);
2021 }
2022 return Local<Uint32>();
2023}
2024
2025
2026int32_t Value::Int32Value() const {
2027 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2028 LOG_API("Int32Value");
2029 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2030 if (obj->IsSmi()) {
2031 return i::Smi::cast(*obj)->value();
2032 } else {
2033 LOG_API("Int32Value (slow)");
2034 ENTER_V8;
2035 EXCEPTION_PREAMBLE();
2036 i::Handle<i::Object> num =
2037 i::Execution::ToInt32(obj, &has_pending_exception);
2038 EXCEPTION_BAILOUT_CHECK(0);
2039 if (num->IsSmi()) {
2040 return i::Smi::cast(*num)->value();
2041 } else {
2042 return static_cast<int32_t>(num->Number());
2043 }
2044 }
2045}
2046
2047
2048bool Value::Equals(Handle<Value> that) const {
2049 if (IsDeadCheck("v8::Value::Equals()")
2050 || EmptyCheck("v8::Value::Equals()", this)
2051 || EmptyCheck("v8::Value::Equals()", that)) {
2052 return false;
2053 }
2054 LOG_API("Equals");
2055 ENTER_V8;
2056 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2057 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2058 i::Object** args[1] = { other.location() };
2059 EXCEPTION_PREAMBLE();
2060 i::Handle<i::Object> result =
2061 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2062 EXCEPTION_BAILOUT_CHECK(false);
2063 return *result == i::Smi::FromInt(i::EQUAL);
2064}
2065
2066
2067bool Value::StrictEquals(Handle<Value> that) const {
2068 if (IsDeadCheck("v8::Value::StrictEquals()")
2069 || EmptyCheck("v8::Value::StrictEquals()", this)
2070 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2071 return false;
2072 }
2073 LOG_API("StrictEquals");
2074 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2075 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2076 // Must check HeapNumber first, since NaN !== NaN.
2077 if (obj->IsHeapNumber()) {
2078 if (!other->IsNumber()) return false;
2079 double x = obj->Number();
2080 double y = other->Number();
2081 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2082 return x == y && !isnan(x) && !isnan(y);
2083 } else if (*obj == *other) { // Also covers Booleans.
2084 return true;
2085 } else if (obj->IsSmi()) {
2086 return other->IsNumber() && obj->Number() == other->Number();
2087 } else if (obj->IsString()) {
2088 return other->IsString() &&
2089 i::String::cast(*obj)->Equals(i::String::cast(*other));
2090 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2091 return other->IsUndefined() || other->IsUndetectableObject();
2092 } else {
2093 return false;
2094 }
2095}
2096
2097
2098uint32_t Value::Uint32Value() const {
2099 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2100 LOG_API("Uint32Value");
2101 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2102 if (obj->IsSmi()) {
2103 return i::Smi::cast(*obj)->value();
2104 } else {
2105 ENTER_V8;
2106 EXCEPTION_PREAMBLE();
2107 i::Handle<i::Object> num =
2108 i::Execution::ToUint32(obj, &has_pending_exception);
2109 EXCEPTION_BAILOUT_CHECK(0);
2110 if (num->IsSmi()) {
2111 return i::Smi::cast(*num)->value();
2112 } else {
2113 return static_cast<uint32_t>(num->Number());
2114 }
2115 }
2116}
2117
2118
2119bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2120 v8::PropertyAttribute attribs) {
2121 ON_BAILOUT("v8::Object::Set()", return false);
2122 ENTER_V8;
2123 HandleScope scope;
2124 i::Handle<i::Object> self = Utils::OpenHandle(this);
2125 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2126 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2127 EXCEPTION_PREAMBLE();
2128 i::Handle<i::Object> obj = i::SetProperty(
2129 self,
2130 key_obj,
2131 value_obj,
2132 static_cast<PropertyAttributes>(attribs));
2133 has_pending_exception = obj.is_null();
2134 EXCEPTION_BAILOUT_CHECK(false);
2135 return true;
2136}
2137
2138
Steve Block6ded16b2010-05-10 14:33:55 +01002139bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2140 ON_BAILOUT("v8::Object::Set()", return false);
2141 ENTER_V8;
2142 HandleScope scope;
2143 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2144 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2145 EXCEPTION_PREAMBLE();
2146 i::Handle<i::Object> obj = i::SetElement(
2147 self,
2148 index,
2149 value_obj);
2150 has_pending_exception = obj.is_null();
2151 EXCEPTION_BAILOUT_CHECK(false);
2152 return true;
2153}
2154
2155
Steve Blocka7e24c12009-10-30 11:49:00 +00002156bool v8::Object::ForceSet(v8::Handle<Value> key,
2157 v8::Handle<Value> value,
2158 v8::PropertyAttribute attribs) {
2159 ON_BAILOUT("v8::Object::ForceSet()", return false);
2160 ENTER_V8;
2161 HandleScope scope;
2162 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2163 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2164 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2165 EXCEPTION_PREAMBLE();
2166 i::Handle<i::Object> obj = i::ForceSetProperty(
2167 self,
2168 key_obj,
2169 value_obj,
2170 static_cast<PropertyAttributes>(attribs));
2171 has_pending_exception = obj.is_null();
2172 EXCEPTION_BAILOUT_CHECK(false);
2173 return true;
2174}
2175
2176
2177bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2178 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2179 ENTER_V8;
2180 HandleScope scope;
2181 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2182 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2183 EXCEPTION_PREAMBLE();
2184 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2185 has_pending_exception = obj.is_null();
2186 EXCEPTION_BAILOUT_CHECK(false);
2187 return obj->IsTrue();
2188}
2189
2190
2191Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2192 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2193 ENTER_V8;
2194 i::Handle<i::Object> self = Utils::OpenHandle(this);
2195 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2196 EXCEPTION_PREAMBLE();
2197 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2198 has_pending_exception = result.is_null();
2199 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2200 return Utils::ToLocal(result);
2201}
2202
2203
Steve Block6ded16b2010-05-10 14:33:55 +01002204Local<Value> v8::Object::Get(uint32_t index) {
2205 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2206 ENTER_V8;
2207 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2208 EXCEPTION_PREAMBLE();
2209 i::Handle<i::Object> result = i::GetElement(self, index);
2210 has_pending_exception = result.is_null();
2211 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2212 return Utils::ToLocal(result);
2213}
2214
2215
Steve Blocka7e24c12009-10-30 11:49:00 +00002216Local<Value> v8::Object::GetPrototype() {
2217 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2218 ENTER_V8;
2219 i::Handle<i::Object> self = Utils::OpenHandle(this);
2220 i::Handle<i::Object> result = i::GetPrototype(self);
2221 return Utils::ToLocal(result);
2222}
2223
2224
Andrei Popescu402d9372010-02-26 13:31:12 +00002225bool v8::Object::SetPrototype(Handle<Value> value) {
2226 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2227 ENTER_V8;
2228 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2229 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2230 EXCEPTION_PREAMBLE();
2231 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2232 has_pending_exception = result.is_null();
2233 EXCEPTION_BAILOUT_CHECK(false);
2234 return true;
2235}
2236
2237
Steve Blocka7e24c12009-10-30 11:49:00 +00002238Local<Object> v8::Object::FindInstanceInPrototypeChain(
2239 v8::Handle<FunctionTemplate> tmpl) {
2240 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2241 return Local<v8::Object>());
2242 ENTER_V8;
2243 i::JSObject* object = *Utils::OpenHandle(this);
2244 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2245 while (!object->IsInstanceOf(tmpl_info)) {
2246 i::Object* prototype = object->GetPrototype();
2247 if (!prototype->IsJSObject()) return Local<Object>();
2248 object = i::JSObject::cast(prototype);
2249 }
2250 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2251}
2252
2253
2254Local<Array> v8::Object::GetPropertyNames() {
2255 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2256 ENTER_V8;
2257 v8::HandleScope scope;
2258 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2259 i::Handle<i::FixedArray> value =
2260 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2261 // Because we use caching to speed up enumeration it is important
2262 // to never change the result of the basic enumeration function so
2263 // we clone the result.
2264 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2265 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2266 return scope.Close(Utils::ToLocal(result));
2267}
2268
2269
2270Local<String> v8::Object::ObjectProtoToString() {
2271 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2272 ENTER_V8;
2273 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2274
2275 i::Handle<i::Object> name(self->class_name());
2276
2277 // Native implementation of Object.prototype.toString (v8natives.js):
2278 // var c = %ClassOf(this);
2279 // if (c === 'Arguments') c = 'Object';
2280 // return "[object " + c + "]";
2281
2282 if (!name->IsString()) {
2283 return v8::String::New("[object ]");
2284
2285 } else {
2286 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2287 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2288 return v8::String::New("[object Object]");
2289
2290 } else {
2291 const char* prefix = "[object ";
2292 Local<String> str = Utils::ToLocal(class_name);
2293 const char* postfix = "]";
2294
Steve Blockd0582a62009-12-15 09:54:21 +00002295 int prefix_len = i::StrLength(prefix);
2296 int str_len = str->Length();
2297 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002298
Steve Blockd0582a62009-12-15 09:54:21 +00002299 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002300 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002301
2302 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002303 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002304 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2305 ptr += prefix_len;
2306
2307 // Write real content.
2308 str->WriteAscii(ptr, 0, str_len);
2309 ptr += str_len;
2310
2311 // Write postfix.
2312 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2313
2314 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002315 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002316 return result;
2317 }
2318 }
2319}
2320
2321
2322bool v8::Object::Delete(v8::Handle<String> key) {
2323 ON_BAILOUT("v8::Object::Delete()", return false);
2324 ENTER_V8;
2325 HandleScope scope;
2326 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2327 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2328 return i::DeleteProperty(self, key_obj)->IsTrue();
2329}
2330
2331
2332bool v8::Object::Has(v8::Handle<String> key) {
2333 ON_BAILOUT("v8::Object::Has()", return false);
2334 ENTER_V8;
2335 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2336 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2337 return self->HasProperty(*key_obj);
2338}
2339
2340
2341bool v8::Object::Delete(uint32_t index) {
2342 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2343 ENTER_V8;
2344 HandleScope scope;
2345 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2346 return i::DeleteElement(self, index)->IsTrue();
2347}
2348
2349
2350bool v8::Object::Has(uint32_t index) {
2351 ON_BAILOUT("v8::Object::HasProperty()", return false);
2352 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2353 return self->HasElement(index);
2354}
2355
2356
2357bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2358 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2359 return Utils::OpenHandle(this)->HasRealNamedProperty(
2360 *Utils::OpenHandle(*key));
2361}
2362
2363
2364bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2365 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2366 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2367}
2368
2369
2370bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2371 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2372 ENTER_V8;
2373 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2374 *Utils::OpenHandle(*key));
2375}
2376
2377
2378bool v8::Object::HasNamedLookupInterceptor() {
2379 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2380 return Utils::OpenHandle(this)->HasNamedInterceptor();
2381}
2382
2383
2384bool v8::Object::HasIndexedLookupInterceptor() {
2385 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2386 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2387}
2388
2389
2390Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2391 Handle<String> key) {
2392 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2393 return Local<Value>());
2394 ENTER_V8;
2395 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2396 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2397 i::LookupResult lookup;
2398 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002399 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002400 PropertyAttributes attributes;
2401 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2402 &lookup,
2403 *key_obj,
2404 &attributes));
2405 return Utils::ToLocal(result);
2406 }
2407 return Local<Value>(); // No real property was found in prototype chain.
2408}
2409
2410
2411Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2412 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2413 ENTER_V8;
2414 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2415 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2416 i::LookupResult lookup;
2417 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002418 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002419 PropertyAttributes attributes;
2420 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2421 &lookup,
2422 *key_obj,
2423 &attributes));
2424 return Utils::ToLocal(result);
2425 }
2426 return Local<Value>(); // No real property was found in prototype chain.
2427}
2428
2429
2430// Turns on access checks by copying the map and setting the check flag.
2431// Because the object gets a new map, existing inline cache caching
2432// the old map of this object will fail.
2433void v8::Object::TurnOnAccessCheck() {
2434 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2435 ENTER_V8;
2436 HandleScope scope;
2437 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2438
2439 i::Handle<i::Map> new_map =
2440 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2441 new_map->set_is_access_check_needed(true);
2442 obj->set_map(*new_map);
2443}
2444
2445
2446bool v8::Object::IsDirty() {
2447 return Utils::OpenHandle(this)->IsDirty();
2448}
2449
2450
2451Local<v8::Object> v8::Object::Clone() {
2452 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2453 ENTER_V8;
2454 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2455 EXCEPTION_PREAMBLE();
2456 i::Handle<i::JSObject> result = i::Copy(self);
2457 has_pending_exception = result.is_null();
2458 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2459 return Utils::ToLocal(result);
2460}
2461
2462
2463int v8::Object::GetIdentityHash() {
2464 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2465 ENTER_V8;
2466 HandleScope scope;
2467 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2468 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2469 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2470 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2471 int hash_value;
2472 if (hash->IsSmi()) {
2473 hash_value = i::Smi::cast(*hash)->value();
2474 } else {
2475 int attempts = 0;
2476 do {
2477 // Generate a random 32-bit hash value but limit range to fit
2478 // within a smi.
2479 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2480 attempts++;
2481 } while (hash_value == 0 && attempts < 30);
2482 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2483 i::SetProperty(hidden_props,
2484 hash_symbol,
2485 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2486 static_cast<PropertyAttributes>(None));
2487 }
2488 return hash_value;
2489}
2490
2491
2492bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2493 v8::Handle<v8::Value> value) {
2494 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2495 ENTER_V8;
2496 HandleScope scope;
2497 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2498 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2499 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2500 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2501 EXCEPTION_PREAMBLE();
2502 i::Handle<i::Object> obj = i::SetProperty(
2503 hidden_props,
2504 key_obj,
2505 value_obj,
2506 static_cast<PropertyAttributes>(None));
2507 has_pending_exception = obj.is_null();
2508 EXCEPTION_BAILOUT_CHECK(false);
2509 return true;
2510}
2511
2512
2513v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2514 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2515 ENTER_V8;
2516 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2517 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2518 if (hidden_props->IsUndefined()) {
2519 return v8::Local<v8::Value>();
2520 }
2521 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2522 EXCEPTION_PREAMBLE();
2523 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2524 has_pending_exception = result.is_null();
2525 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2526 if (result->IsUndefined()) {
2527 return v8::Local<v8::Value>();
2528 }
2529 return Utils::ToLocal(result);
2530}
2531
2532
2533bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2534 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2535 ENTER_V8;
2536 HandleScope scope;
2537 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2538 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2539 if (hidden_props->IsUndefined()) {
2540 return true;
2541 }
2542 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2543 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2544 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2545}
2546
2547
2548void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2549 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2550 ENTER_V8;
2551 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002552 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002553 "v8::Object::SetIndexedPropertiesToPixelData()",
2554 "length exceeds max acceptable value")) {
2555 return;
2556 }
2557 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2558 if (!ApiCheck(!self->IsJSArray(),
2559 "v8::Object::SetIndexedPropertiesToPixelData()",
2560 "JSArray is not supported")) {
2561 return;
2562 }
2563 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2564 self->set_elements(*pixels);
2565}
2566
2567
Steve Block3ce2e202009-11-05 08:53:23 +00002568void v8::Object::SetIndexedPropertiesToExternalArrayData(
2569 void* data,
2570 ExternalArrayType array_type,
2571 int length) {
2572 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2573 ENTER_V8;
2574 HandleScope scope;
2575 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2576 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2577 "length exceeds max acceptable value")) {
2578 return;
2579 }
2580 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2581 if (!ApiCheck(!self->IsJSArray(),
2582 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2583 "JSArray is not supported")) {
2584 return;
2585 }
2586 i::Handle<i::ExternalArray> array =
2587 i::Factory::NewExternalArray(length, array_type, data);
2588 self->set_elements(*array);
2589}
2590
2591
Steve Blocka7e24c12009-10-30 11:49:00 +00002592Local<v8::Object> Function::NewInstance() const {
2593 return NewInstance(0, NULL);
2594}
2595
2596
2597Local<v8::Object> Function::NewInstance(int argc,
2598 v8::Handle<v8::Value> argv[]) const {
2599 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2600 LOG_API("Function::NewInstance");
2601 ENTER_V8;
2602 HandleScope scope;
2603 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2604 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2605 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2606 EXCEPTION_PREAMBLE();
2607 i::Handle<i::Object> returned =
2608 i::Execution::New(function, argc, args, &has_pending_exception);
2609 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2610 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2611}
2612
2613
2614Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2615 v8::Handle<v8::Value> argv[]) {
2616 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2617 LOG_API("Function::Call");
2618 ENTER_V8;
2619 i::Object* raw_result = NULL;
2620 {
2621 HandleScope scope;
2622 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2623 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2624 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2625 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2626 EXCEPTION_PREAMBLE();
2627 i::Handle<i::Object> returned =
2628 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2629 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2630 raw_result = *returned;
2631 }
2632 i::Handle<i::Object> result(raw_result);
2633 return Utils::ToLocal(result);
2634}
2635
2636
2637void Function::SetName(v8::Handle<v8::String> name) {
2638 ENTER_V8;
2639 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2640 func->shared()->set_name(*Utils::OpenHandle(*name));
2641}
2642
2643
2644Handle<Value> Function::GetName() const {
2645 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2646 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2647}
2648
2649
Andrei Popescu402d9372010-02-26 13:31:12 +00002650ScriptOrigin Function::GetScriptOrigin() const {
2651 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2652 if (func->shared()->script()->IsScript()) {
2653 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2654 v8::ScriptOrigin origin(
2655 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2656 v8::Integer::New(script->line_offset()->value()),
2657 v8::Integer::New(script->column_offset()->value()));
2658 return origin;
2659 }
2660 return v8::ScriptOrigin(Handle<Value>());
2661}
2662
2663
2664const int Function::kLineOffsetNotFound = -1;
2665
2666
2667int Function::GetScriptLineNumber() const {
2668 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2669 if (func->shared()->script()->IsScript()) {
2670 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2671 return i::GetScriptLineNumber(script, func->shared()->start_position());
2672 }
2673 return kLineOffsetNotFound;
2674}
2675
2676
2677namespace {
2678
2679// Tracks string usage to help make better decisions when
2680// externalizing strings.
2681//
2682// Implementation note: internally this class only tracks fresh
2683// strings and keeps a single use counter for them.
2684class StringTracker {
2685 public:
2686 // Records that the given string's characters were copied to some
2687 // external buffer. If this happens often we should honor
2688 // externalization requests for the string.
2689 static void RecordWrite(i::Handle<i::String> string) {
2690 i::Address address = reinterpret_cast<i::Address>(*string);
2691 i::Address top = i::Heap::NewSpaceTop();
2692 if (IsFreshString(address, top)) {
2693 IncrementUseCount(top);
2694 }
2695 }
2696
2697 // Estimates freshness and use frequency of the given string based
2698 // on how close it is to the new space top and the recorded usage
2699 // history.
2700 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2701 i::Address address = reinterpret_cast<i::Address>(*string);
2702 i::Address top = i::Heap::NewSpaceTop();
2703 return IsFreshString(address, top) && IsUseCountLow(top);
2704 }
2705
2706 private:
2707 static inline bool IsFreshString(i::Address string, i::Address top) {
2708 return top - kFreshnessLimit <= string && string <= top;
2709 }
2710
2711 static inline bool IsUseCountLow(i::Address top) {
2712 if (last_top_ != top) return true;
2713 return use_count_ < kUseLimit;
2714 }
2715
2716 static inline void IncrementUseCount(i::Address top) {
2717 if (last_top_ != top) {
2718 use_count_ = 0;
2719 last_top_ = top;
2720 }
2721 ++use_count_;
2722 }
2723
2724 // How close to the new space top a fresh string has to be.
2725 static const int kFreshnessLimit = 1024;
2726
2727 // The number of uses required to consider a string useful.
2728 static const int kUseLimit = 32;
2729
2730 // Single use counter shared by all fresh strings.
2731 static int use_count_;
2732
2733 // Last new space top when the use count above was valid.
2734 static i::Address last_top_;
2735};
2736
2737int StringTracker::use_count_ = 0;
2738i::Address StringTracker::last_top_ = NULL;
2739
2740} // namespace
2741
2742
Steve Blocka7e24c12009-10-30 11:49:00 +00002743int String::Length() const {
2744 if (IsDeadCheck("v8::String::Length()")) return 0;
2745 return Utils::OpenHandle(this)->length();
2746}
2747
2748
2749int String::Utf8Length() const {
2750 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2751 return Utils::OpenHandle(this)->Utf8Length();
2752}
2753
2754
Steve Block6ded16b2010-05-10 14:33:55 +01002755int String::WriteUtf8(char* buffer,
2756 int capacity,
2757 int* nchars_ref,
2758 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002759 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2760 LOG_API("String::WriteUtf8");
2761 ENTER_V8;
2762 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002763 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002764 if (hints & HINT_MANY_WRITES_EXPECTED) {
2765 // Flatten the string for efficiency. This applies whether we are
2766 // using StringInputBuffer or Get(i) to access the characters.
2767 str->TryFlatten();
2768 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002769 write_input_buffer.Reset(0, *str);
2770 int len = str->length();
2771 // Encode the first K - 3 bytes directly into the buffer since we
2772 // know there's room for them. If no capacity is given we copy all
2773 // of them here.
2774 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2775 int i;
2776 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002777 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002778 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2779 i::uc32 c = write_input_buffer.GetNext();
2780 int written = unibrow::Utf8::Encode(buffer + pos, c);
2781 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002782 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002783 }
2784 if (i < len) {
2785 // For the last characters we need to check the length for each one
2786 // because they may be longer than the remaining space in the
2787 // buffer.
2788 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2789 for (; i < len && pos < capacity; i++) {
2790 i::uc32 c = write_input_buffer.GetNext();
2791 int written = unibrow::Utf8::Encode(intermediate, c);
2792 if (pos + written <= capacity) {
2793 for (int j = 0; j < written; j++)
2794 buffer[pos + j] = intermediate[j];
2795 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002796 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002797 } else {
2798 // We've reached the end of the buffer
2799 break;
2800 }
2801 }
2802 }
Steve Block6ded16b2010-05-10 14:33:55 +01002803 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002804 if (i == len && (capacity == -1 || pos < capacity))
2805 buffer[pos++] = '\0';
2806 return pos;
2807}
2808
2809
Steve Block6ded16b2010-05-10 14:33:55 +01002810int String::WriteAscii(char* buffer,
2811 int start,
2812 int length,
2813 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002814 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2815 LOG_API("String::WriteAscii");
2816 ENTER_V8;
2817 ASSERT(start >= 0 && length >= -1);
2818 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002819 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002820 if (hints & HINT_MANY_WRITES_EXPECTED) {
2821 // Flatten the string for efficiency. This applies whether we are
2822 // using StringInputBuffer or Get(i) to access the characters.
2823 str->TryFlatten();
2824 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002825 int end = length;
2826 if ( (length == -1) || (length > str->length() - start) )
2827 end = str->length() - start;
2828 if (end < 0) return 0;
2829 write_input_buffer.Reset(start, *str);
2830 int i;
2831 for (i = 0; i < end; i++) {
2832 char c = static_cast<char>(write_input_buffer.GetNext());
2833 if (c == '\0') c = ' ';
2834 buffer[i] = c;
2835 }
2836 if (length == -1 || i < length)
2837 buffer[i] = '\0';
2838 return i;
2839}
2840
2841
Steve Block6ded16b2010-05-10 14:33:55 +01002842int String::Write(uint16_t* buffer,
2843 int start,
2844 int length,
2845 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002846 if (IsDeadCheck("v8::String::Write()")) return 0;
2847 LOG_API("String::Write");
2848 ENTER_V8;
2849 ASSERT(start >= 0 && length >= -1);
2850 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002851 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002852 if (hints & HINT_MANY_WRITES_EXPECTED) {
2853 // Flatten the string for efficiency. This applies whether we are
2854 // using StringInputBuffer or Get(i) to access the characters.
2855 str->TryFlatten();
2856 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002857 int end = length;
2858 if ( (length == -1) || (length > str->length() - start) )
2859 end = str->length() - start;
2860 if (end < 0) return 0;
2861 i::String::WriteToFlat(*str, buffer, start, end);
2862 if (length == -1 || end < length)
2863 buffer[end] = '\0';
2864 return end;
2865}
2866
2867
2868bool v8::String::IsExternal() const {
2869 EnsureInitialized("v8::String::IsExternal()");
2870 i::Handle<i::String> str = Utils::OpenHandle(this);
2871 return i::StringShape(*str).IsExternalTwoByte();
2872}
2873
2874
2875bool v8::String::IsExternalAscii() const {
2876 EnsureInitialized("v8::String::IsExternalAscii()");
2877 i::Handle<i::String> str = Utils::OpenHandle(this);
2878 return i::StringShape(*str).IsExternalAscii();
2879}
2880
2881
2882void v8::String::VerifyExternalStringResource(
2883 v8::String::ExternalStringResource* value) const {
2884 i::Handle<i::String> str = Utils::OpenHandle(this);
2885 v8::String::ExternalStringResource* expected;
2886 if (i::StringShape(*str).IsExternalTwoByte()) {
2887 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2888 expected = reinterpret_cast<ExternalStringResource*>(resource);
2889 } else {
2890 expected = NULL;
2891 }
2892 CHECK_EQ(expected, value);
2893}
2894
2895
2896v8::String::ExternalAsciiStringResource*
2897 v8::String::GetExternalAsciiStringResource() const {
2898 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2899 i::Handle<i::String> str = Utils::OpenHandle(this);
2900 if (i::StringShape(*str).IsExternalAscii()) {
2901 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2902 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2903 } else {
2904 return NULL;
2905 }
2906}
2907
2908
2909double Number::Value() const {
2910 if (IsDeadCheck("v8::Number::Value()")) return 0;
2911 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2912 return obj->Number();
2913}
2914
2915
2916bool Boolean::Value() const {
2917 if (IsDeadCheck("v8::Boolean::Value()")) return false;
2918 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2919 return obj->IsTrue();
2920}
2921
2922
2923int64_t Integer::Value() const {
2924 if (IsDeadCheck("v8::Integer::Value()")) return 0;
2925 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2926 if (obj->IsSmi()) {
2927 return i::Smi::cast(*obj)->value();
2928 } else {
2929 return static_cast<int64_t>(obj->Number());
2930 }
2931}
2932
2933
2934int32_t Int32::Value() const {
2935 if (IsDeadCheck("v8::Int32::Value()")) return 0;
2936 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2937 if (obj->IsSmi()) {
2938 return i::Smi::cast(*obj)->value();
2939 } else {
2940 return static_cast<int32_t>(obj->Number());
2941 }
2942}
2943
2944
Steve Block6ded16b2010-05-10 14:33:55 +01002945uint32_t Uint32::Value() const {
2946 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
2947 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2948 if (obj->IsSmi()) {
2949 return i::Smi::cast(*obj)->value();
2950 } else {
2951 return static_cast<uint32_t>(obj->Number());
2952 }
2953}
2954
2955
Steve Blocka7e24c12009-10-30 11:49:00 +00002956int v8::Object::InternalFieldCount() {
2957 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2958 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2959 return obj->GetInternalFieldCount();
2960}
2961
2962
2963Local<Value> v8::Object::CheckedGetInternalField(int index) {
2964 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
2965 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2966 if (!ApiCheck(index < obj->GetInternalFieldCount(),
2967 "v8::Object::GetInternalField()",
2968 "Reading internal field out of bounds")) {
2969 return Local<Value>();
2970 }
2971 i::Handle<i::Object> value(obj->GetInternalField(index));
2972 Local<Value> result = Utils::ToLocal(value);
2973#ifdef DEBUG
2974 Local<Value> unchecked = UncheckedGetInternalField(index);
2975 ASSERT(unchecked.IsEmpty() || (unchecked == result));
2976#endif
2977 return result;
2978}
2979
2980
2981void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2982 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
2983 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2984 if (!ApiCheck(index < obj->GetInternalFieldCount(),
2985 "v8::Object::SetInternalField()",
2986 "Writing internal field out of bounds")) {
2987 return;
2988 }
2989 ENTER_V8;
2990 i::Handle<i::Object> val = Utils::OpenHandle(*value);
2991 obj->SetInternalField(index, *val);
2992}
2993
2994
2995void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01002996 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00002997 i::Object* as_object = reinterpret_cast<i::Object*>(value);
2998 if (as_object->IsSmi()) {
2999 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3000 return;
3001 }
3002 HandleScope scope;
3003 i::Handle<i::Proxy> proxy =
3004 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3005 if (!proxy.is_null())
3006 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003007}
3008
3009
3010// --- E n v i r o n m e n t ---
3011
3012bool v8::V8::Initialize() {
3013 if (i::V8::IsRunning()) return true;
3014 ENTER_V8;
3015 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003016 if (i::Snapshot::Initialize()) return true;
3017 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003018}
3019
3020
3021bool v8::V8::Dispose() {
3022 i::V8::TearDown();
3023 return true;
3024}
3025
3026
Steve Block3ce2e202009-11-05 08:53:23 +00003027HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3028
3029
3030void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3031 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3032 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3033}
3034
3035
3036bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003037 // Returning true tells the caller that it need not
3038 // continue to call IdleNotification.
3039 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003040 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003041}
3042
3043
3044void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003045 if (!i::V8::IsRunning()) return;
3046 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003047}
3048
3049
Steve Block6ded16b2010-05-10 14:33:55 +01003050int v8::V8::ContextDisposedNotification() {
3051 if (!i::V8::IsRunning()) return 0;
3052 return i::Heap::NotifyContextDisposed();
3053}
3054
3055
Steve Blocka7e24c12009-10-30 11:49:00 +00003056const char* v8::V8::GetVersion() {
3057 static v8::internal::EmbeddedVector<char, 128> buffer;
3058 v8::internal::Version::GetString(buffer);
3059 return buffer.start();
3060}
3061
3062
3063static i::Handle<i::FunctionTemplateInfo>
3064 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3065 if (templ->constructor()->IsUndefined()) {
3066 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3067 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3068 templ->set_constructor(*Utils::OpenHandle(*constructor));
3069 }
3070 return i::Handle<i::FunctionTemplateInfo>(
3071 i::FunctionTemplateInfo::cast(templ->constructor()));
3072}
3073
3074
3075Persistent<Context> v8::Context::New(
3076 v8::ExtensionConfiguration* extensions,
3077 v8::Handle<ObjectTemplate> global_template,
3078 v8::Handle<Value> global_object) {
3079 EnsureInitialized("v8::Context::New()");
3080 LOG_API("Context::New");
3081 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3082
3083 // Enter V8 via an ENTER_V8 scope.
3084 i::Handle<i::Context> env;
3085 {
3086 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003087 v8::Handle<ObjectTemplate> proxy_template = global_template;
3088 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3089 i::Handle<i::FunctionTemplateInfo> global_constructor;
3090
3091 if (!global_template.IsEmpty()) {
3092 // Make sure that the global_template has a constructor.
3093 global_constructor =
3094 EnsureConstructor(Utils::OpenHandle(*global_template));
3095
3096 // Create a fresh template for the global proxy object.
3097 proxy_template = ObjectTemplate::New();
3098 proxy_constructor =
3099 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3100
3101 // Set the global template to be the prototype template of
3102 // global proxy template.
3103 proxy_constructor->set_prototype_template(
3104 *Utils::OpenHandle(*global_template));
3105
3106 // Migrate security handlers from global_template to
3107 // proxy_template. Temporarily removing access check
3108 // information from the global template.
3109 if (!global_constructor->access_check_info()->IsUndefined()) {
3110 proxy_constructor->set_access_check_info(
3111 global_constructor->access_check_info());
3112 proxy_constructor->set_needs_access_check(
3113 global_constructor->needs_access_check());
3114 global_constructor->set_needs_access_check(false);
3115 global_constructor->set_access_check_info(i::Heap::undefined_value());
3116 }
3117 }
3118
3119 // Create the environment.
3120 env = i::Bootstrapper::CreateEnvironment(
3121 Utils::OpenHandle(*global_object),
3122 proxy_template,
3123 extensions);
3124
3125 // Restore the access check info on the global template.
3126 if (!global_template.IsEmpty()) {
3127 ASSERT(!global_constructor.is_null());
3128 ASSERT(!proxy_constructor.is_null());
3129 global_constructor->set_access_check_info(
3130 proxy_constructor->access_check_info());
3131 global_constructor->set_needs_access_check(
3132 proxy_constructor->needs_access_check());
3133 }
3134 }
3135 // Leave V8.
3136
3137 if (env.is_null())
3138 return Persistent<Context>();
3139 return Persistent<Context>(Utils::ToLocal(env));
3140}
3141
3142
3143void v8::Context::SetSecurityToken(Handle<Value> token) {
3144 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3145 ENTER_V8;
3146 i::Handle<i::Context> env = Utils::OpenHandle(this);
3147 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3148 env->set_security_token(*token_handle);
3149}
3150
3151
3152void v8::Context::UseDefaultSecurityToken() {
3153 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3154 ENTER_V8;
3155 i::Handle<i::Context> env = Utils::OpenHandle(this);
3156 env->set_security_token(env->global());
3157}
3158
3159
3160Handle<Value> v8::Context::GetSecurityToken() {
3161 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3162 i::Handle<i::Context> env = Utils::OpenHandle(this);
3163 i::Object* security_token = env->security_token();
3164 i::Handle<i::Object> token_handle(security_token);
3165 return Utils::ToLocal(token_handle);
3166}
3167
3168
3169bool Context::HasOutOfMemoryException() {
3170 i::Handle<i::Context> env = Utils::OpenHandle(this);
3171 return env->has_out_of_memory();
3172}
3173
3174
3175bool Context::InContext() {
3176 return i::Top::context() != NULL;
3177}
3178
3179
3180v8::Local<v8::Context> Context::GetEntered() {
3181 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3182 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3183 if (last.is_null()) return Local<Context>();
3184 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3185 return Utils::ToLocal(context);
3186}
3187
3188
3189v8::Local<v8::Context> Context::GetCurrent() {
3190 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003191 i::Handle<i::Object> current = i::Top::global_context();
3192 if (current.is_null()) return Local<Context>();
3193 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003194 return Utils::ToLocal(context);
3195}
3196
3197
3198v8::Local<v8::Context> Context::GetCalling() {
3199 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3200 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3201 if (calling.is_null()) return Local<Context>();
3202 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3203 return Utils::ToLocal(context);
3204}
3205
3206
3207v8::Local<v8::Object> Context::Global() {
3208 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3209 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3210 i::Handle<i::Context> context =
3211 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3212 i::Handle<i::Object> global(context->global_proxy());
3213 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3214}
3215
3216
3217void Context::DetachGlobal() {
3218 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3219 ENTER_V8;
3220 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3221 i::Handle<i::Context> context =
3222 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3223 i::Bootstrapper::DetachGlobal(context);
3224}
3225
3226
Andrei Popescu74b3c142010-03-29 12:03:09 +01003227void Context::ReattachGlobal(Handle<Object> global_object) {
3228 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3229 ENTER_V8;
3230 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3231 i::Handle<i::Context> context =
3232 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3233 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3234}
3235
3236
Steve Blocka7e24c12009-10-30 11:49:00 +00003237Local<v8::Object> ObjectTemplate::NewInstance() {
3238 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3239 LOG_API("ObjectTemplate::NewInstance");
3240 ENTER_V8;
3241 EXCEPTION_PREAMBLE();
3242 i::Handle<i::Object> obj =
3243 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3244 &has_pending_exception);
3245 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3246 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3247}
3248
3249
3250Local<v8::Function> FunctionTemplate::GetFunction() {
3251 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3252 return Local<v8::Function>());
3253 LOG_API("FunctionTemplate::GetFunction");
3254 ENTER_V8;
3255 EXCEPTION_PREAMBLE();
3256 i::Handle<i::Object> obj =
3257 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3258 &has_pending_exception);
3259 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3260 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3261}
3262
3263
3264bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3265 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3266 i::Object* obj = *Utils::OpenHandle(*value);
3267 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3268}
3269
3270
3271static Local<External> ExternalNewImpl(void* data) {
3272 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3273}
3274
3275static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3276 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3277}
3278
3279
Steve Blocka7e24c12009-10-30 11:49:00 +00003280Local<Value> v8::External::Wrap(void* data) {
3281 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3282 LOG_API("External::Wrap");
3283 EnsureInitialized("v8::External::Wrap()");
3284 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003285 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3286 if (as_object->IsSmi()) {
3287 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003288 }
3289 return ExternalNewImpl(data);
3290}
3291
3292
Steve Block3ce2e202009-11-05 08:53:23 +00003293void* v8::Object::SlowGetPointerFromInternalField(int index) {
3294 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3295 i::Object* value = obj->GetInternalField(index);
3296 if (value->IsSmi()) {
3297 return value;
3298 } else if (value->IsProxy()) {
3299 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3300 } else {
3301 return NULL;
3302 }
3303}
3304
3305
Steve Blocka7e24c12009-10-30 11:49:00 +00003306void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3307 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3308 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3309 void* result;
3310 if (obj->IsSmi()) {
3311 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003312 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003313 } else if (obj->IsProxy()) {
3314 result = ExternalValueImpl(obj);
3315 } else {
3316 result = NULL;
3317 }
3318 ASSERT_EQ(result, QuickUnwrap(wrapper));
3319 return result;
3320}
3321
3322
3323Local<External> v8::External::New(void* data) {
3324 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3325 LOG_API("External::New");
3326 EnsureInitialized("v8::External::New()");
3327 ENTER_V8;
3328 return ExternalNewImpl(data);
3329}
3330
3331
3332void* External::Value() const {
3333 if (IsDeadCheck("v8::External::Value()")) return 0;
3334 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3335 return ExternalValueImpl(obj);
3336}
3337
3338
3339Local<String> v8::String::Empty() {
3340 EnsureInitialized("v8::String::Empty()");
3341 LOG_API("String::Empty()");
3342 return Utils::ToLocal(i::Factory::empty_symbol());
3343}
3344
3345
3346Local<String> v8::String::New(const char* data, int length) {
3347 EnsureInitialized("v8::String::New()");
3348 LOG_API("String::New(char)");
3349 if (length == 0) return Empty();
3350 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003351 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003352 i::Handle<i::String> result =
3353 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3354 return Utils::ToLocal(result);
3355}
3356
3357
Steve Block3ce2e202009-11-05 08:53:23 +00003358Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3359 EnsureInitialized("v8::String::New()");
3360 LOG_API("String::New(char)");
3361 ENTER_V8;
3362 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3363 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3364 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3365 right_string);
3366 return Utils::ToLocal(result);
3367}
3368
3369
Steve Blocka7e24c12009-10-30 11:49:00 +00003370Local<String> v8::String::NewUndetectable(const char* data, int length) {
3371 EnsureInitialized("v8::String::NewUndetectable()");
3372 LOG_API("String::NewUndetectable(char)");
3373 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003374 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003375 i::Handle<i::String> result =
3376 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3377 result->MarkAsUndetectable();
3378 return Utils::ToLocal(result);
3379}
3380
3381
3382static int TwoByteStringLength(const uint16_t* data) {
3383 int length = 0;
3384 while (data[length] != '\0') length++;
3385 return length;
3386}
3387
3388
3389Local<String> v8::String::New(const uint16_t* data, int length) {
3390 EnsureInitialized("v8::String::New()");
3391 LOG_API("String::New(uint16_)");
3392 if (length == 0) return Empty();
3393 ENTER_V8;
3394 if (length == -1) length = TwoByteStringLength(data);
3395 i::Handle<i::String> result =
3396 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3397 return Utils::ToLocal(result);
3398}
3399
3400
3401Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3402 EnsureInitialized("v8::String::NewUndetectable()");
3403 LOG_API("String::NewUndetectable(uint16_)");
3404 ENTER_V8;
3405 if (length == -1) length = TwoByteStringLength(data);
3406 i::Handle<i::String> result =
3407 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3408 result->MarkAsUndetectable();
3409 return Utils::ToLocal(result);
3410}
3411
3412
3413i::Handle<i::String> NewExternalStringHandle(
3414 v8::String::ExternalStringResource* resource) {
3415 i::Handle<i::String> result =
3416 i::Factory::NewExternalStringFromTwoByte(resource);
3417 return result;
3418}
3419
3420
3421i::Handle<i::String> NewExternalAsciiStringHandle(
3422 v8::String::ExternalAsciiStringResource* resource) {
3423 i::Handle<i::String> result =
3424 i::Factory::NewExternalStringFromAscii(resource);
3425 return result;
3426}
3427
3428
Steve Blocka7e24c12009-10-30 11:49:00 +00003429Local<String> v8::String::NewExternal(
3430 v8::String::ExternalStringResource* resource) {
3431 EnsureInitialized("v8::String::NewExternal()");
3432 LOG_API("String::NewExternal");
3433 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003434 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003435 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003436 return Utils::ToLocal(result);
3437}
3438
3439
3440bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3441 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3442 if (this->IsExternal()) return false; // Already an external string.
3443 ENTER_V8;
3444 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003445 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003446 bool result = obj->MakeExternal(resource);
3447 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003448 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003449 }
3450 return result;
3451}
3452
3453
3454Local<String> v8::String::NewExternal(
3455 v8::String::ExternalAsciiStringResource* resource) {
3456 EnsureInitialized("v8::String::NewExternal()");
3457 LOG_API("String::NewExternal");
3458 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003459 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003460 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003461 return Utils::ToLocal(result);
3462}
3463
3464
3465bool v8::String::MakeExternal(
3466 v8::String::ExternalAsciiStringResource* resource) {
3467 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3468 if (this->IsExternal()) return false; // Already an external string.
3469 ENTER_V8;
3470 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003471 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003472 bool result = obj->MakeExternal(resource);
3473 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003474 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003475 }
3476 return result;
3477}
3478
3479
3480bool v8::String::CanMakeExternal() {
3481 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3482 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003483 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003484 int size = obj->Size(); // Byte size of the original string.
3485 if (size < i::ExternalString::kSize)
3486 return false;
3487 i::StringShape shape(*obj);
3488 return !shape.IsExternal();
3489}
3490
3491
3492Local<v8::Object> v8::Object::New() {
3493 EnsureInitialized("v8::Object::New()");
3494 LOG_API("Object::New");
3495 ENTER_V8;
3496 i::Handle<i::JSObject> obj =
3497 i::Factory::NewJSObject(i::Top::object_function());
3498 return Utils::ToLocal(obj);
3499}
3500
3501
3502Local<v8::Value> v8::Date::New(double time) {
3503 EnsureInitialized("v8::Date::New()");
3504 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003505 if (isnan(time)) {
3506 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3507 time = i::OS::nan_value();
3508 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003509 ENTER_V8;
3510 EXCEPTION_PREAMBLE();
3511 i::Handle<i::Object> obj =
3512 i::Execution::NewDate(time, &has_pending_exception);
3513 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3514 return Utils::ToLocal(obj);
3515}
3516
3517
3518double v8::Date::NumberValue() const {
3519 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3520 LOG_API("Date::NumberValue");
3521 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3522 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3523 return jsvalue->value()->Number();
3524}
3525
3526
3527Local<v8::Array> v8::Array::New(int length) {
3528 EnsureInitialized("v8::Array::New()");
3529 LOG_API("Array::New");
3530 ENTER_V8;
3531 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3532 return Utils::ToLocal(obj);
3533}
3534
3535
3536uint32_t v8::Array::Length() const {
3537 if (IsDeadCheck("v8::Array::Length()")) return 0;
3538 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3539 i::Object* length = obj->length();
3540 if (length->IsSmi()) {
3541 return i::Smi::cast(length)->value();
3542 } else {
3543 return static_cast<uint32_t>(length->Number());
3544 }
3545}
3546
3547
3548Local<Object> Array::CloneElementAt(uint32_t index) {
3549 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3550 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3551 if (!self->HasFastElements()) {
3552 return Local<Object>();
3553 }
3554 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3555 i::Object* paragon = elms->get(index);
3556 if (!paragon->IsJSObject()) {
3557 return Local<Object>();
3558 }
3559 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3560 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003561 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003562 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3563 has_pending_exception = result.is_null();
3564 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3565 return Utils::ToLocal(result);
3566}
3567
3568
3569Local<String> v8::String::NewSymbol(const char* data, int length) {
3570 EnsureInitialized("v8::String::NewSymbol()");
3571 LOG_API("String::NewSymbol(char)");
3572 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003573 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003574 i::Handle<i::String> result =
3575 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3576 return Utils::ToLocal(result);
3577}
3578
3579
3580Local<Number> v8::Number::New(double value) {
3581 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003582 if (isnan(value)) {
3583 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3584 value = i::OS::nan_value();
3585 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003586 ENTER_V8;
3587 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3588 return Utils::NumberToLocal(result);
3589}
3590
3591
3592Local<Integer> v8::Integer::New(int32_t value) {
3593 EnsureInitialized("v8::Integer::New()");
3594 if (i::Smi::IsValid(value)) {
3595 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3596 }
3597 ENTER_V8;
3598 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3599 return Utils::IntegerToLocal(result);
3600}
3601
3602
Steve Block3ce2e202009-11-05 08:53:23 +00003603Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3604 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3605 if (fits_into_int32_t) {
3606 return Integer::New(static_cast<int32_t>(value));
3607 }
3608 ENTER_V8;
3609 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3610 return Utils::IntegerToLocal(result);
3611}
3612
3613
Steve Blocka7e24c12009-10-30 11:49:00 +00003614void V8::IgnoreOutOfMemoryException() {
3615 thread_local.set_ignore_out_of_memory(true);
3616}
3617
3618
3619bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3620 EnsureInitialized("v8::V8::AddMessageListener()");
3621 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3622 ENTER_V8;
3623 HandleScope scope;
3624 NeanderArray listeners(i::Factory::message_listeners());
3625 NeanderObject obj(2);
3626 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3627 obj.set(1, data.IsEmpty() ?
3628 i::Heap::undefined_value() :
3629 *Utils::OpenHandle(*data));
3630 listeners.add(obj.value());
3631 return true;
3632}
3633
3634
3635void V8::RemoveMessageListeners(MessageCallback that) {
3636 EnsureInitialized("v8::V8::RemoveMessageListener()");
3637 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3638 ENTER_V8;
3639 HandleScope scope;
3640 NeanderArray listeners(i::Factory::message_listeners());
3641 for (int i = 0; i < listeners.length(); i++) {
3642 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3643
3644 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3645 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3646 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3647 listeners.set(i, i::Heap::undefined_value());
3648 }
3649 }
3650}
3651
3652
3653void V8::SetCounterFunction(CounterLookupCallback callback) {
3654 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3655 i::StatsTable::SetCounterFunction(callback);
3656}
3657
3658void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3659 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3660 i::StatsTable::SetCreateHistogramFunction(callback);
3661}
3662
3663void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3664 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3665 i::StatsTable::SetAddHistogramSampleFunction(callback);
3666}
3667
3668void V8::EnableSlidingStateWindow() {
3669 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3670 i::Logger::EnableSlidingStateWindow();
3671}
3672
3673
3674void V8::SetFailedAccessCheckCallbackFunction(
3675 FailedAccessCheckCallback callback) {
3676 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3677 i::Top::SetFailedAccessCheckCallback(callback);
3678}
3679
3680
3681void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3682 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3683 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3684 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3685}
3686
3687
3688int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3689 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3690 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3691}
3692
3693
3694void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3695 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3696 i::Heap::SetGlobalGCPrologueCallback(callback);
3697}
3698
3699
3700void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3701 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3702 i::Heap::SetGlobalGCEpilogueCallback(callback);
3703}
3704
3705
Steve Block6ded16b2010-05-10 14:33:55 +01003706void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3707 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3708 i::Heap::AddGCPrologueCallback(callback, gc_type);
3709}
3710
3711
3712void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3713 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3714 i::Heap::RemoveGCPrologueCallback(callback);
3715}
3716
3717
3718void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3719 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3720 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3721}
3722
3723
3724void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3725 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3726 i::Heap::RemoveGCEpilogueCallback(callback);
3727}
3728
3729
Steve Blocka7e24c12009-10-30 11:49:00 +00003730void V8::PauseProfiler() {
3731#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003732 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003733#endif
3734}
3735
3736
3737void V8::ResumeProfiler() {
3738#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003739 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003740#endif
3741}
3742
3743
3744bool V8::IsProfilerPaused() {
3745#ifdef ENABLE_LOGGING_AND_PROFILING
3746 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3747#else
3748 return true;
3749#endif
3750}
3751
3752
Andrei Popescu402d9372010-02-26 13:31:12 +00003753void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003754#ifdef ENABLE_LOGGING_AND_PROFILING
3755 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3756 // Snapshot mode: resume modules, perform GC, then pause only
3757 // those modules which haven't been started prior to making a
3758 // snapshot.
3759
Steve Block6ded16b2010-05-10 14:33:55 +01003760 // Make a GC prior to taking a snapshot.
3761 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003762 // Reset snapshot flag and CPU module flags.
3763 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3764 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003765 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003766 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003767 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003768 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003769 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003770 }
3771#endif
3772}
3773
3774
Andrei Popescu402d9372010-02-26 13:31:12 +00003775void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003776#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003777 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003778#endif
3779}
3780
3781
3782int V8::GetActiveProfilerModules() {
3783#ifdef ENABLE_LOGGING_AND_PROFILING
3784 return i::Logger::GetActiveProfilerModules();
3785#else
3786 return PROFILER_MODULE_NONE;
3787#endif
3788}
3789
3790
3791int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3792#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003793 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003794 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3795#endif
3796 return 0;
3797}
3798
3799
3800int V8::GetCurrentThreadId() {
3801 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3802 EnsureInitialized("V8::GetCurrentThreadId()");
3803 return i::Top::thread_id();
3804}
3805
3806
3807void V8::TerminateExecution(int thread_id) {
3808 if (!i::V8::IsRunning()) return;
3809 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3810 // If the thread_id identifies the current thread just terminate
3811 // execution right away. Otherwise, ask the thread manager to
3812 // terminate the thread with the given id if any.
3813 if (thread_id == i::Top::thread_id()) {
3814 i::StackGuard::TerminateExecution();
3815 } else {
3816 i::ThreadManager::TerminateExecution(thread_id);
3817 }
3818}
3819
3820
3821void V8::TerminateExecution() {
3822 if (!i::V8::IsRunning()) return;
3823 i::StackGuard::TerminateExecution();
3824}
3825
3826
Steve Block6ded16b2010-05-10 14:33:55 +01003827bool V8::IsExecutionTerminating() {
3828 if (!i::V8::IsRunning()) return false;
3829 if (i::Top::has_scheduled_exception()) {
3830 return i::Top::scheduled_exception() == i::Heap::termination_exception();
3831 }
3832 return false;
3833}
3834
3835
Steve Blocka7e24c12009-10-30 11:49:00 +00003836String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3837 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3838 if (obj.IsEmpty()) {
3839 str_ = NULL;
3840 length_ = 0;
3841 return;
3842 }
3843 ENTER_V8;
3844 HandleScope scope;
3845 TryCatch try_catch;
3846 Handle<String> str = obj->ToString();
3847 if (str.IsEmpty()) {
3848 str_ = NULL;
3849 length_ = 0;
3850 } else {
3851 length_ = str->Utf8Length();
3852 str_ = i::NewArray<char>(length_ + 1);
3853 str->WriteUtf8(str_);
3854 }
3855}
3856
3857
3858String::Utf8Value::~Utf8Value() {
3859 i::DeleteArray(str_);
3860}
3861
3862
3863String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3864 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3865 if (obj.IsEmpty()) {
3866 str_ = NULL;
3867 length_ = 0;
3868 return;
3869 }
3870 ENTER_V8;
3871 HandleScope scope;
3872 TryCatch try_catch;
3873 Handle<String> str = obj->ToString();
3874 if (str.IsEmpty()) {
3875 str_ = NULL;
3876 length_ = 0;
3877 } else {
3878 length_ = str->Length();
3879 str_ = i::NewArray<char>(length_ + 1);
3880 str->WriteAscii(str_);
3881 }
3882}
3883
3884
3885String::AsciiValue::~AsciiValue() {
3886 i::DeleteArray(str_);
3887}
3888
3889
3890String::Value::Value(v8::Handle<v8::Value> obj) {
3891 EnsureInitialized("v8::String::Value::Value()");
3892 if (obj.IsEmpty()) {
3893 str_ = NULL;
3894 length_ = 0;
3895 return;
3896 }
3897 ENTER_V8;
3898 HandleScope scope;
3899 TryCatch try_catch;
3900 Handle<String> str = obj->ToString();
3901 if (str.IsEmpty()) {
3902 str_ = NULL;
3903 length_ = 0;
3904 } else {
3905 length_ = str->Length();
3906 str_ = i::NewArray<uint16_t>(length_ + 1);
3907 str->Write(str_);
3908 }
3909}
3910
3911
3912String::Value::~Value() {
3913 i::DeleteArray(str_);
3914}
3915
3916Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3917 LOG_API("RangeError");
3918 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
3919 ENTER_V8;
3920 i::Object* error;
3921 {
3922 HandleScope scope;
3923 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3924 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3925 error = *result;
3926 }
3927 i::Handle<i::Object> result(error);
3928 return Utils::ToLocal(result);
3929}
3930
3931Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3932 LOG_API("ReferenceError");
3933 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
3934 ENTER_V8;
3935 i::Object* error;
3936 {
3937 HandleScope scope;
3938 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3939 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3940 error = *result;
3941 }
3942 i::Handle<i::Object> result(error);
3943 return Utils::ToLocal(result);
3944}
3945
3946Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3947 LOG_API("SyntaxError");
3948 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
3949 ENTER_V8;
3950 i::Object* error;
3951 {
3952 HandleScope scope;
3953 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3954 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3955 error = *result;
3956 }
3957 i::Handle<i::Object> result(error);
3958 return Utils::ToLocal(result);
3959}
3960
3961Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
3962 LOG_API("TypeError");
3963 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
3964 ENTER_V8;
3965 i::Object* error;
3966 {
3967 HandleScope scope;
3968 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3969 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
3970 error = *result;
3971 }
3972 i::Handle<i::Object> result(error);
3973 return Utils::ToLocal(result);
3974}
3975
3976Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
3977 LOG_API("Error");
3978 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
3979 ENTER_V8;
3980 i::Object* error;
3981 {
3982 HandleScope scope;
3983 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3984 i::Handle<i::Object> result = i::Factory::NewError(message);
3985 error = *result;
3986 }
3987 i::Handle<i::Object> result(error);
3988 return Utils::ToLocal(result);
3989}
3990
3991
3992// --- D e b u g S u p p o r t ---
3993
3994#ifdef ENABLE_DEBUGGER_SUPPORT
3995bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
3996 EnsureInitialized("v8::Debug::SetDebugEventListener()");
3997 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3998 ENTER_V8;
3999 HandleScope scope;
4000 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4001 if (that != NULL) {
4002 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4003 }
4004 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4005 return true;
4006}
4007
4008
4009bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4010 Handle<Value> data) {
4011 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4012 ENTER_V8;
4013 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4014 Utils::OpenHandle(*data));
4015 return true;
4016}
4017
4018
4019void Debug::DebugBreak() {
4020 if (!i::V8::IsRunning()) return;
4021 i::StackGuard::DebugBreak();
4022}
4023
4024
4025static v8::Debug::MessageHandler message_handler = NULL;
4026
4027static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4028 if (message_handler) {
4029 v8::String::Value json(message.GetJSON());
4030 message_handler(*json, json.length(), message.GetClientData());
4031 }
4032}
4033
4034
4035void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4036 bool message_handler_thread) {
4037 EnsureInitialized("v8::Debug::SetMessageHandler");
4038 ENTER_V8;
4039 // Message handler thread not supported any more. Parameter temporally left in
4040 // the API for client compatability reasons.
4041 CHECK(!message_handler_thread);
4042
4043 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4044 message_handler = handler;
4045 if (message_handler != NULL) {
4046 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4047 } else {
4048 i::Debugger::SetMessageHandler(NULL);
4049 }
4050}
4051
4052
4053void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4054 EnsureInitialized("v8::Debug::SetMessageHandler");
4055 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004056 i::Debugger::SetMessageHandler(handler);
4057}
4058
4059
4060void Debug::SendCommand(const uint16_t* command, int length,
4061 ClientData* client_data) {
4062 if (!i::V8::IsRunning()) return;
4063 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4064 client_data);
4065}
4066
4067
4068void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4069 int period) {
4070 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4071 ENTER_V8;
4072 i::Debugger::SetHostDispatchHandler(handler, period);
4073}
4074
4075
Steve Blockd0582a62009-12-15 09:54:21 +00004076void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004077 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004078 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4079 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004080 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004081}
4082
4083
Steve Blocka7e24c12009-10-30 11:49:00 +00004084Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4085 v8::Handle<v8::Value> data) {
4086 if (!i::V8::IsRunning()) return Local<Value>();
4087 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4088 ENTER_V8;
4089 i::Handle<i::Object> result;
4090 EXCEPTION_PREAMBLE();
4091 if (data.IsEmpty()) {
4092 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4093 i::Factory::undefined_value(),
4094 &has_pending_exception);
4095 } else {
4096 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4097 Utils::OpenHandle(*data),
4098 &has_pending_exception);
4099 }
4100 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4101 return Utils::ToLocal(result);
4102}
4103
4104
4105Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4106 if (!i::V8::IsRunning()) return Local<Value>();
4107 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4108 ENTER_V8;
4109 v8::HandleScope scope;
4110 i::Debug::Load();
4111 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4112 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4113 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4114 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4115 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4116 const int kArgc = 1;
4117 v8::Handle<v8::Value> argv[kArgc] = { obj };
4118 EXCEPTION_PREAMBLE();
4119 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4120 kArgc,
4121 argv);
4122 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4123 return scope.Close(result);
4124}
4125
4126
Leon Clarkee46be812010-01-19 14:06:41 +00004127bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4128 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004129}
Leon Clarkee46be812010-01-19 14:06:41 +00004130
4131void Debug::ProcessDebugMessages() {
4132 i::Execution::ProcessDebugMesssages(true);
4133}
4134
Steve Block6ded16b2010-05-10 14:33:55 +01004135Local<Context> Debug::GetDebugContext() {
4136 EnsureInitialized("v8::Debug::GetDebugContext()");
4137 ENTER_V8;
4138 return Utils::ToLocal(i::Debugger::GetDebugContext());
4139}
4140
Steve Blocka7e24c12009-10-30 11:49:00 +00004141#endif // ENABLE_DEBUGGER_SUPPORT
4142
Steve Block6ded16b2010-05-10 14:33:55 +01004143
4144#ifdef ENABLE_LOGGING_AND_PROFILING
4145
4146Handle<String> CpuProfileNode::GetFunctionName() const {
4147 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4148 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4149 const i::CodeEntry* entry = node->entry();
4150 if (!entry->has_name_prefix()) {
4151 return Handle<String>(ToApi<String>(
4152 i::Factory::LookupAsciiSymbol(entry->name())));
4153 } else {
4154 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4155 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4156 i::Factory::LookupAsciiSymbol(entry->name()))));
4157 }
4158}
4159
4160
4161Handle<String> CpuProfileNode::GetScriptResourceName() const {
4162 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4163 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4164 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4165 node->entry()->resource_name())));
4166}
4167
4168
4169int CpuProfileNode::GetLineNumber() const {
4170 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4171 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4172}
4173
4174
4175double CpuProfileNode::GetTotalTime() const {
4176 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4177 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4178}
4179
4180
4181double CpuProfileNode::GetSelfTime() const {
4182 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4183 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4184}
4185
4186
4187double CpuProfileNode::GetTotalSamplesCount() const {
4188 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4189 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4190}
4191
4192
4193double CpuProfileNode::GetSelfSamplesCount() const {
4194 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4195 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4196}
4197
4198
4199unsigned CpuProfileNode::GetCallUid() const {
4200 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4201 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4202}
4203
4204
4205int CpuProfileNode::GetChildrenCount() const {
4206 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4207 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4208}
4209
4210
4211const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4212 IsDeadCheck("v8::CpuProfileNode::GetChild");
4213 const i::ProfileNode* child =
4214 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4215 return reinterpret_cast<const CpuProfileNode*>(child);
4216}
4217
4218
4219unsigned CpuProfile::GetUid() const {
4220 IsDeadCheck("v8::CpuProfile::GetUid");
4221 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4222}
4223
4224
4225Handle<String> CpuProfile::GetTitle() const {
4226 IsDeadCheck("v8::CpuProfile::GetTitle");
4227 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4228 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4229 profile->title())));
4230}
4231
4232
4233const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4234 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4235 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4236 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4237}
4238
4239
4240const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4241 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4242 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4243 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4244}
4245
4246
4247int CpuProfiler::GetProfilesCount() {
4248 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4249 return i::CpuProfiler::GetProfilesCount();
4250}
4251
4252
4253const CpuProfile* CpuProfiler::GetProfile(int index) {
4254 IsDeadCheck("v8::CpuProfiler::GetProfile");
4255 return reinterpret_cast<const CpuProfile*>(i::CpuProfiler::GetProfile(index));
4256}
4257
4258
4259const CpuProfile* CpuProfiler::FindProfile(unsigned uid) {
4260 IsDeadCheck("v8::CpuProfiler::FindProfile");
4261 return reinterpret_cast<const CpuProfile*>(i::CpuProfiler::FindProfile(uid));
4262}
4263
4264
4265void CpuProfiler::StartProfiling(Handle<String> title) {
4266 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4267 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4268}
4269
4270
4271const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
4272 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4273 return reinterpret_cast<const CpuProfile*>(
4274 i::CpuProfiler::StopProfiling(*Utils::OpenHandle(*title)));
4275}
4276
4277#endif // ENABLE_LOGGING_AND_PROFILING
4278
4279
Steve Blocka7e24c12009-10-30 11:49:00 +00004280namespace internal {
4281
4282
4283HandleScopeImplementer* HandleScopeImplementer::instance() {
4284 return &thread_local;
4285}
4286
4287
4288void HandleScopeImplementer::FreeThreadResources() {
4289 thread_local.Free();
4290}
4291
4292
4293char* HandleScopeImplementer::ArchiveThread(char* storage) {
4294 return thread_local.ArchiveThreadHelper(storage);
4295}
4296
4297
4298char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4299 v8::ImplementationUtilities::HandleScopeData* current =
4300 v8::ImplementationUtilities::CurrentHandleScope();
4301 handle_scope_data_ = *current;
4302 memcpy(storage, this, sizeof(*this));
4303
4304 ResetAfterArchive();
4305 current->Initialize();
4306
4307 return storage + ArchiveSpacePerThread();
4308}
4309
4310
4311int HandleScopeImplementer::ArchiveSpacePerThread() {
4312 return sizeof(thread_local);
4313}
4314
4315
4316char* HandleScopeImplementer::RestoreThread(char* storage) {
4317 return thread_local.RestoreThreadHelper(storage);
4318}
4319
4320
4321char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4322 memcpy(this, storage, sizeof(*this));
4323 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4324 return storage + ArchiveSpacePerThread();
4325}
4326
4327
4328void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4329 // Iterate over all handles in the blocks except for the last.
4330 for (int i = blocks()->length() - 2; i >= 0; --i) {
4331 Object** block = blocks()->at(i);
4332 v->VisitPointers(block, &block[kHandleBlockSize]);
4333 }
4334
4335 // Iterate over live handles in the last block (if any).
4336 if (!blocks()->is_empty()) {
4337 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4338 }
4339
4340 if (!saved_contexts_.is_empty()) {
4341 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4342 v->VisitPointers(start, start + saved_contexts_.length());
4343 }
4344}
4345
4346
4347void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4348 v8::ImplementationUtilities::HandleScopeData* current =
4349 v8::ImplementationUtilities::CurrentHandleScope();
4350 thread_local.handle_scope_data_ = *current;
4351 thread_local.IterateThis(v);
4352}
4353
4354
4355char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4356 HandleScopeImplementer* thread_local =
4357 reinterpret_cast<HandleScopeImplementer*>(storage);
4358 thread_local->IterateThis(v);
4359 return storage + ArchiveSpacePerThread();
4360}
4361
4362} } // namespace v8::internal