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