blob: a7948aeb54b63159ed0b8def33e6f506dfd19052 [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
856void FunctionTemplate::SetNamedInstancePropertyHandler(
857 NamedPropertyGetter getter,
858 NamedPropertySetter setter,
859 NamedPropertyQuery query,
860 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
990void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
991 NamedPropertySetter setter,
992 NamedPropertyQuery query,
993 NamedPropertyDeleter remover,
994 NamedPropertyEnumerator enumerator,
995 Handle<Value> data) {
996 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
997 ENTER_V8;
998 HandleScope scope;
999 EnsureConstructor(this);
1000 i::FunctionTemplateInfo* constructor =
1001 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1002 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1003 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1004 setter,
1005 query,
1006 remover,
1007 enumerator,
1008 data);
1009}
1010
1011
1012void ObjectTemplate::MarkAsUndetectable() {
1013 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1014 ENTER_V8;
1015 HandleScope scope;
1016 EnsureConstructor(this);
1017 i::FunctionTemplateInfo* constructor =
1018 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1019 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1020 cons->set_undetectable(true);
1021}
1022
1023
1024void ObjectTemplate::SetAccessCheckCallbacks(
1025 NamedSecurityCallback named_callback,
1026 IndexedSecurityCallback indexed_callback,
1027 Handle<Value> data,
1028 bool turned_on_by_default) {
1029 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1030 ENTER_V8;
1031 HandleScope scope;
1032 EnsureConstructor(this);
1033
1034 i::Handle<i::Struct> struct_info =
1035 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1036 i::Handle<i::AccessCheckInfo> info =
1037 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1038 info->set_named_callback(*FromCData(named_callback));
1039 info->set_indexed_callback(*FromCData(indexed_callback));
1040 if (data.IsEmpty()) data = v8::Undefined();
1041 info->set_data(*Utils::OpenHandle(*data));
1042
1043 i::FunctionTemplateInfo* constructor =
1044 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1045 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1046 cons->set_access_check_info(*info);
1047 cons->set_needs_access_check(turned_on_by_default);
1048}
1049
1050
1051void ObjectTemplate::SetIndexedPropertyHandler(
1052 IndexedPropertyGetter getter,
1053 IndexedPropertySetter setter,
1054 IndexedPropertyQuery query,
1055 IndexedPropertyDeleter remover,
1056 IndexedPropertyEnumerator enumerator,
1057 Handle<Value> data) {
1058 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1059 ENTER_V8;
1060 HandleScope scope;
1061 EnsureConstructor(this);
1062 i::FunctionTemplateInfo* constructor =
1063 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1064 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1065 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1066 setter,
1067 query,
1068 remover,
1069 enumerator,
1070 data);
1071}
1072
1073
1074void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1075 Handle<Value> data) {
1076 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1077 ENTER_V8;
1078 HandleScope scope;
1079 EnsureConstructor(this);
1080 i::FunctionTemplateInfo* constructor =
1081 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1082 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1083 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1084}
1085
1086
1087int ObjectTemplate::InternalFieldCount() {
1088 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1089 return 0;
1090 }
1091 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1092}
1093
1094
1095void ObjectTemplate::SetInternalFieldCount(int value) {
1096 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1097 if (!ApiCheck(i::Smi::IsValid(value),
1098 "v8::ObjectTemplate::SetInternalFieldCount()",
1099 "Invalid internal field count")) {
1100 return;
1101 }
1102 ENTER_V8;
1103 if (value > 0) {
1104 // The internal field count is set by the constructor function's
1105 // construct code, so we ensure that there is a constructor
1106 // function to do the setting.
1107 EnsureConstructor(this);
1108 }
1109 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1110}
1111
1112
1113// --- S c r i p t D a t a ---
1114
1115
1116ScriptData* ScriptData::PreCompile(const char* input, int length) {
1117 unibrow::Utf8InputBuffer<> buf(input, length);
1118 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1119}
1120
1121
Leon Clarkef7060e22010-06-03 12:02:55 +01001122ScriptData* ScriptData::New(const char* data, int length) {
1123 // Return an empty ScriptData if the length is obviously invalid.
1124 if (length % sizeof(unsigned) != 0) {
1125 return new i::ScriptDataImpl(i::Vector<unsigned>());
1126 }
1127
1128 // Copy the data to ensure it is properly aligned.
1129 int deserialized_data_length = length / sizeof(unsigned);
1130 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
1131 memcpy(deserialized_data, data, length);
1132
1133 return new i::ScriptDataImpl(
1134 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001135}
1136
1137
1138// --- S c r i p t ---
1139
1140
1141Local<Script> Script::New(v8::Handle<String> source,
1142 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001143 v8::ScriptData* pre_data,
1144 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001145 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1146 LOG_API("Script::New");
1147 ENTER_V8;
1148 i::Handle<i::String> str = Utils::OpenHandle(*source);
1149 i::Handle<i::Object> name_obj;
1150 int line_offset = 0;
1151 int column_offset = 0;
1152 if (origin != NULL) {
1153 if (!origin->ResourceName().IsEmpty()) {
1154 name_obj = Utils::OpenHandle(*origin->ResourceName());
1155 }
1156 if (!origin->ResourceLineOffset().IsEmpty()) {
1157 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1158 }
1159 if (!origin->ResourceColumnOffset().IsEmpty()) {
1160 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1161 }
1162 }
1163 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001164 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 // We assert that the pre-data is sane, even though we can actually
1166 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001167 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001168 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001169 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1170 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001171 }
Steve Block6ded16b2010-05-10 14:33:55 +01001172 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001173 i::Compiler::Compile(str,
1174 name_obj,
1175 line_offset,
1176 column_offset,
1177 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001178 pre_data_impl,
1179 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001180 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001181 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001183 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001184}
1185
1186
1187Local<Script> Script::New(v8::Handle<String> source,
1188 v8::Handle<Value> file_name) {
1189 ScriptOrigin origin(file_name);
1190 return New(source, &origin);
1191}
1192
1193
1194Local<Script> Script::Compile(v8::Handle<String> source,
1195 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001196 v8::ScriptData* pre_data,
1197 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1199 LOG_API("Script::Compile");
1200 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001201 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001202 if (generic.IsEmpty())
1203 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001204 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1205 i::Handle<i::SharedFunctionInfo> function =
1206 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001207 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001208 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1209 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001210 return Local<Script>(ToApi<Script>(result));
1211}
1212
1213
1214Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001215 v8::Handle<Value> file_name,
1216 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001218 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001219}
1220
1221
1222Local<Value> Script::Run() {
1223 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1224 LOG_API("Script::Run");
1225 ENTER_V8;
1226 i::Object* raw_result = NULL;
1227 {
1228 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001229 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1230 i::Handle<i::JSFunction> fun;
1231 if (obj->IsSharedFunctionInfo()) {
1232 i::Handle<i::SharedFunctionInfo>
1233 function_info(i::SharedFunctionInfo::cast(*obj));
1234 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1235 function_info, i::Top::global_context());
1236 } else {
1237 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 }
1239 EXCEPTION_PREAMBLE();
1240 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1241 i::Handle<i::Object> result =
1242 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1243 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1244 raw_result = *result;
1245 }
1246 i::Handle<i::Object> result(raw_result);
1247 return Utils::ToLocal(result);
1248}
1249
1250
Steve Block6ded16b2010-05-10 14:33:55 +01001251static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1252 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1253 i::Handle<i::SharedFunctionInfo> result;
1254 if (obj->IsSharedFunctionInfo()) {
1255 result =
1256 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1257 } else {
1258 result =
1259 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1260 }
1261 return result;
1262}
1263
1264
Steve Blocka7e24c12009-10-30 11:49:00 +00001265Local<Value> Script::Id() {
1266 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1267 LOG_API("Script::Id");
1268 i::Object* raw_id = NULL;
1269 {
1270 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001271 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1272 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 i::Handle<i::Object> id(script->id());
1274 raw_id = *id;
1275 }
1276 i::Handle<i::Object> id(raw_id);
1277 return Utils::ToLocal(id);
1278}
1279
1280
Steve Blockd0582a62009-12-15 09:54:21 +00001281void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001282 ON_BAILOUT("v8::Script::SetData()", return);
1283 LOG_API("Script::SetData");
1284 {
1285 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001286 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001287 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001288 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 script->set_data(*raw_data);
1290 }
1291}
1292
1293
1294// --- E x c e p t i o n s ---
1295
1296
1297v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001298 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 exception_(i::Heap::the_hole_value()),
1300 message_(i::Smi::FromInt(0)),
1301 is_verbose_(false),
1302 can_continue_(true),
1303 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001304 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 i::Top::RegisterTryCatchHandler(this);
1306}
1307
1308
1309v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001310 if (rethrow_) {
1311 v8::HandleScope scope;
1312 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1313 i::Top::UnregisterTryCatchHandler(this);
1314 v8::ThrowException(exc);
1315 } else {
1316 i::Top::UnregisterTryCatchHandler(this);
1317 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001318}
1319
1320
1321bool v8::TryCatch::HasCaught() const {
1322 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1323}
1324
1325
1326bool v8::TryCatch::CanContinue() const {
1327 return can_continue_;
1328}
1329
1330
Steve Blockd0582a62009-12-15 09:54:21 +00001331v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1332 if (!HasCaught()) return v8::Local<v8::Value>();
1333 rethrow_ = true;
1334 return v8::Undefined();
1335}
1336
1337
Steve Blocka7e24c12009-10-30 11:49:00 +00001338v8::Local<Value> v8::TryCatch::Exception() const {
1339 if (HasCaught()) {
1340 // Check for out of memory exception.
1341 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1342 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1343 } else {
1344 return v8::Local<Value>();
1345 }
1346}
1347
1348
1349v8::Local<Value> v8::TryCatch::StackTrace() const {
1350 if (HasCaught()) {
1351 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1352 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1353 v8::HandleScope scope;
1354 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1355 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1356 if (!obj->HasProperty(*name))
1357 return v8::Local<Value>();
1358 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1359 } else {
1360 return v8::Local<Value>();
1361 }
1362}
1363
1364
1365v8::Local<v8::Message> v8::TryCatch::Message() const {
1366 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1367 i::Object* message = reinterpret_cast<i::Object*>(message_);
1368 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1369 } else {
1370 return v8::Local<v8::Message>();
1371 }
1372}
1373
1374
1375void v8::TryCatch::Reset() {
1376 exception_ = i::Heap::the_hole_value();
1377 message_ = i::Smi::FromInt(0);
1378}
1379
1380
1381void v8::TryCatch::SetVerbose(bool value) {
1382 is_verbose_ = value;
1383}
1384
1385
1386void v8::TryCatch::SetCaptureMessage(bool value) {
1387 capture_message_ = value;
1388}
1389
1390
1391// --- M e s s a g e ---
1392
1393
1394Local<String> Message::Get() const {
1395 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1396 ENTER_V8;
1397 HandleScope scope;
1398 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1399 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1400 Local<String> result = Utils::ToLocal(raw_result);
1401 return scope.Close(result);
1402}
1403
1404
1405v8::Handle<Value> Message::GetScriptResourceName() const {
1406 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1407 return Local<String>();
1408 }
1409 ENTER_V8;
1410 HandleScope scope;
1411 i::Handle<i::JSObject> obj =
1412 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1413 // Return this.script.name.
1414 i::Handle<i::JSValue> script =
1415 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1416 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1417 return scope.Close(Utils::ToLocal(resource_name));
1418}
1419
1420
1421v8::Handle<Value> Message::GetScriptData() const {
1422 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1423 return Local<Value>();
1424 }
1425 ENTER_V8;
1426 HandleScope scope;
1427 i::Handle<i::JSObject> obj =
1428 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1429 // Return this.script.data.
1430 i::Handle<i::JSValue> script =
1431 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1432 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1433 return scope.Close(Utils::ToLocal(data));
1434}
1435
1436
1437static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1438 i::Handle<i::Object> recv,
1439 int argc,
1440 i::Object** argv[],
1441 bool* has_pending_exception) {
1442 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1443 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1444 i::Handle<i::JSFunction> fun =
1445 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1446 i::Handle<i::Object> value =
1447 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1448 return value;
1449}
1450
1451
1452static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1453 i::Handle<i::Object> data,
1454 bool* has_pending_exception) {
1455 i::Object** argv[1] = { data.location() };
1456 return CallV8HeapFunction(name,
1457 i::Top::builtins(),
1458 1,
1459 argv,
1460 has_pending_exception);
1461}
1462
1463
1464int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001465 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 ENTER_V8;
1467 HandleScope scope;
1468 EXCEPTION_PREAMBLE();
1469 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1470 Utils::OpenHandle(this),
1471 &has_pending_exception);
1472 EXCEPTION_BAILOUT_CHECK(0);
1473 return static_cast<int>(result->Number());
1474}
1475
1476
1477int Message::GetStartPosition() const {
1478 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1479 ENTER_V8;
1480 HandleScope scope;
1481
1482 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1483 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1484}
1485
1486
1487int Message::GetEndPosition() const {
1488 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1489 ENTER_V8;
1490 HandleScope scope;
1491 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1492 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1493}
1494
1495
1496int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001497 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001498 ENTER_V8;
1499 HandleScope scope;
1500 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1501 EXCEPTION_PREAMBLE();
1502 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1503 "GetPositionInLine",
1504 data_obj,
1505 &has_pending_exception);
1506 EXCEPTION_BAILOUT_CHECK(0);
1507 return static_cast<int>(start_col_obj->Number());
1508}
1509
1510
1511int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001512 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001513 ENTER_V8;
1514 HandleScope scope;
1515 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1516 EXCEPTION_PREAMBLE();
1517 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1518 "GetPositionInLine",
1519 data_obj,
1520 &has_pending_exception);
1521 EXCEPTION_BAILOUT_CHECK(0);
1522 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1523 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1524 return static_cast<int>(start_col_obj->Number()) + (end - start);
1525}
1526
1527
1528Local<String> Message::GetSourceLine() const {
1529 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1530 ENTER_V8;
1531 HandleScope scope;
1532 EXCEPTION_PREAMBLE();
1533 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1534 Utils::OpenHandle(this),
1535 &has_pending_exception);
1536 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1537 if (result->IsString()) {
1538 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1539 } else {
1540 return Local<String>();
1541 }
1542}
1543
1544
1545void Message::PrintCurrentStackTrace(FILE* out) {
1546 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1547 ENTER_V8;
1548 i::Top::PrintCurrentStackTrace(out);
1549}
1550
1551
Kristian Monsen25f61362010-05-21 11:50:48 +01001552// --- S t a c k T r a c e ---
1553
1554Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1555 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1556 ENTER_V8;
1557 HandleScope scope;
1558 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1559 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1560 return scope.Close(Utils::StackFrameToLocal(obj));
1561}
1562
1563
1564int StackTrace::GetFrameCount() const {
1565 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1566 ENTER_V8;
1567 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1568}
1569
1570
1571Local<Array> StackTrace::AsArray() {
1572 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1573 ENTER_V8;
1574 return Utils::ToLocal(Utils::OpenHandle(this));
1575}
1576
1577
1578Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1579 StackTraceOptions options) {
1580 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1581 ENTER_V8;
1582 return i::Top::CaptureCurrentStackTrace(frame_limit, options);
1583}
1584
1585
1586// --- S t a c k F r a m e ---
1587
1588int StackFrame::GetLineNumber() const {
1589 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1590 return Message::kNoLineNumberInfo;
1591 }
1592 ENTER_V8;
1593 i::HandleScope scope;
1594 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1595 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1596 if (!line->IsSmi()) {
1597 return Message::kNoLineNumberInfo;
1598 }
1599 return i::Smi::cast(*line)->value();
1600}
1601
1602
1603int StackFrame::GetColumn() const {
1604 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1605 return Message::kNoColumnInfo;
1606 }
1607 ENTER_V8;
1608 i::HandleScope scope;
1609 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1610 i::Handle<i::Object> column = GetProperty(self, "column");
1611 if (!column->IsSmi()) {
1612 return Message::kNoColumnInfo;
1613 }
1614 return i::Smi::cast(*column)->value();
1615}
1616
1617
1618Local<String> StackFrame::GetScriptName() const {
1619 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1620 ENTER_V8;
1621 HandleScope scope;
1622 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1623 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1624 if (!name->IsString()) {
1625 return Local<String>();
1626 }
1627 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1628}
1629
1630
1631Local<String> StackFrame::GetFunctionName() const {
1632 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1633 ENTER_V8;
1634 HandleScope scope;
1635 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1636 i::Handle<i::Object> name = GetProperty(self, "functionName");
1637 if (!name->IsString()) {
1638 return Local<String>();
1639 }
1640 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1641}
1642
1643
1644bool StackFrame::IsEval() const {
1645 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1646 ENTER_V8;
1647 i::HandleScope scope;
1648 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1649 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1650 return is_eval->IsTrue();
1651}
1652
1653
1654bool StackFrame::IsConstructor() const {
1655 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1656 ENTER_V8;
1657 i::HandleScope scope;
1658 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1659 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1660 return is_constructor->IsTrue();
1661}
1662
1663
Steve Blocka7e24c12009-10-30 11:49:00 +00001664// --- D a t a ---
1665
1666bool Value::IsUndefined() const {
1667 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1668 return Utils::OpenHandle(this)->IsUndefined();
1669}
1670
1671
1672bool Value::IsNull() const {
1673 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1674 return Utils::OpenHandle(this)->IsNull();
1675}
1676
1677
1678bool Value::IsTrue() const {
1679 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1680 return Utils::OpenHandle(this)->IsTrue();
1681}
1682
1683
1684bool Value::IsFalse() const {
1685 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1686 return Utils::OpenHandle(this)->IsFalse();
1687}
1688
1689
1690bool Value::IsFunction() const {
1691 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1692 return Utils::OpenHandle(this)->IsJSFunction();
1693}
1694
1695
1696bool Value::FullIsString() const {
1697 if (IsDeadCheck("v8::Value::IsString()")) return false;
1698 bool result = Utils::OpenHandle(this)->IsString();
1699 ASSERT_EQ(result, QuickIsString());
1700 return result;
1701}
1702
1703
1704bool Value::IsArray() const {
1705 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1706 return Utils::OpenHandle(this)->IsJSArray();
1707}
1708
1709
1710bool Value::IsObject() const {
1711 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1712 return Utils::OpenHandle(this)->IsJSObject();
1713}
1714
1715
1716bool Value::IsNumber() const {
1717 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1718 return Utils::OpenHandle(this)->IsNumber();
1719}
1720
1721
1722bool Value::IsBoolean() const {
1723 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1724 return Utils::OpenHandle(this)->IsBoolean();
1725}
1726
1727
1728bool Value::IsExternal() const {
1729 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1730 return Utils::OpenHandle(this)->IsProxy();
1731}
1732
1733
1734bool Value::IsInt32() const {
1735 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1736 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1737 if (obj->IsSmi()) return true;
1738 if (obj->IsNumber()) {
1739 double value = obj->Number();
1740 return i::FastI2D(i::FastD2I(value)) == value;
1741 }
1742 return false;
1743}
1744
1745
Steve Block6ded16b2010-05-10 14:33:55 +01001746bool Value::IsUint32() const {
1747 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1748 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1749 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1750 if (obj->IsNumber()) {
1751 double value = obj->Number();
1752 return i::FastUI2D(i::FastD2UI(value)) == value;
1753 }
1754 return false;
1755}
1756
1757
Steve Blocka7e24c12009-10-30 11:49:00 +00001758bool Value::IsDate() const {
1759 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1760 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1761 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1762}
1763
1764
1765Local<String> Value::ToString() const {
1766 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1767 LOG_API("ToString");
1768 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1769 i::Handle<i::Object> str;
1770 if (obj->IsString()) {
1771 str = obj;
1772 } else {
1773 ENTER_V8;
1774 EXCEPTION_PREAMBLE();
1775 str = i::Execution::ToString(obj, &has_pending_exception);
1776 EXCEPTION_BAILOUT_CHECK(Local<String>());
1777 }
1778 return Local<String>(ToApi<String>(str));
1779}
1780
1781
1782Local<String> Value::ToDetailString() const {
1783 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1784 LOG_API("ToDetailString");
1785 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1786 i::Handle<i::Object> str;
1787 if (obj->IsString()) {
1788 str = obj;
1789 } else {
1790 ENTER_V8;
1791 EXCEPTION_PREAMBLE();
1792 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1793 EXCEPTION_BAILOUT_CHECK(Local<String>());
1794 }
1795 return Local<String>(ToApi<String>(str));
1796}
1797
1798
1799Local<v8::Object> Value::ToObject() const {
1800 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1801 LOG_API("ToObject");
1802 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1803 i::Handle<i::Object> val;
1804 if (obj->IsJSObject()) {
1805 val = obj;
1806 } else {
1807 ENTER_V8;
1808 EXCEPTION_PREAMBLE();
1809 val = i::Execution::ToObject(obj, &has_pending_exception);
1810 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1811 }
1812 return Local<v8::Object>(ToApi<Object>(val));
1813}
1814
1815
1816Local<Boolean> Value::ToBoolean() const {
1817 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1818 LOG_API("ToBoolean");
1819 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1820 if (obj->IsBoolean()) {
1821 return Local<Boolean>(ToApi<Boolean>(obj));
1822 } else {
1823 ENTER_V8;
1824 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1825 return Local<Boolean>(ToApi<Boolean>(val));
1826 }
1827}
1828
1829
1830Local<Number> Value::ToNumber() const {
1831 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1832 LOG_API("ToNumber");
1833 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1834 i::Handle<i::Object> num;
1835 if (obj->IsNumber()) {
1836 num = obj;
1837 } else {
1838 ENTER_V8;
1839 EXCEPTION_PREAMBLE();
1840 num = i::Execution::ToNumber(obj, &has_pending_exception);
1841 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1842 }
1843 return Local<Number>(ToApi<Number>(num));
1844}
1845
1846
1847Local<Integer> Value::ToInteger() const {
1848 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1849 LOG_API("ToInteger");
1850 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1851 i::Handle<i::Object> num;
1852 if (obj->IsSmi()) {
1853 num = obj;
1854 } else {
1855 ENTER_V8;
1856 EXCEPTION_PREAMBLE();
1857 num = i::Execution::ToInteger(obj, &has_pending_exception);
1858 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1859 }
1860 return Local<Integer>(ToApi<Integer>(num));
1861}
1862
1863
1864void External::CheckCast(v8::Value* that) {
1865 if (IsDeadCheck("v8::External::Cast()")) return;
1866 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1867 ApiCheck(obj->IsProxy(),
1868 "v8::External::Cast()",
1869 "Could not convert to external");
1870}
1871
1872
1873void v8::Object::CheckCast(Value* that) {
1874 if (IsDeadCheck("v8::Object::Cast()")) return;
1875 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1876 ApiCheck(obj->IsJSObject(),
1877 "v8::Object::Cast()",
1878 "Could not convert to object");
1879}
1880
1881
1882void v8::Function::CheckCast(Value* that) {
1883 if (IsDeadCheck("v8::Function::Cast()")) return;
1884 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1885 ApiCheck(obj->IsJSFunction(),
1886 "v8::Function::Cast()",
1887 "Could not convert to function");
1888}
1889
1890
1891void v8::String::CheckCast(v8::Value* that) {
1892 if (IsDeadCheck("v8::String::Cast()")) return;
1893 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1894 ApiCheck(obj->IsString(),
1895 "v8::String::Cast()",
1896 "Could not convert to string");
1897}
1898
1899
1900void v8::Number::CheckCast(v8::Value* that) {
1901 if (IsDeadCheck("v8::Number::Cast()")) return;
1902 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1903 ApiCheck(obj->IsNumber(),
1904 "v8::Number::Cast()",
1905 "Could not convert to number");
1906}
1907
1908
1909void v8::Integer::CheckCast(v8::Value* that) {
1910 if (IsDeadCheck("v8::Integer::Cast()")) return;
1911 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1912 ApiCheck(obj->IsNumber(),
1913 "v8::Integer::Cast()",
1914 "Could not convert to number");
1915}
1916
1917
1918void v8::Array::CheckCast(Value* that) {
1919 if (IsDeadCheck("v8::Array::Cast()")) return;
1920 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1921 ApiCheck(obj->IsJSArray(),
1922 "v8::Array::Cast()",
1923 "Could not convert to array");
1924}
1925
1926
1927void v8::Date::CheckCast(v8::Value* that) {
1928 if (IsDeadCheck("v8::Date::Cast()")) return;
1929 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1930 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1931 "v8::Date::Cast()",
1932 "Could not convert to date");
1933}
1934
1935
1936bool Value::BooleanValue() const {
1937 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1938 LOG_API("BooleanValue");
1939 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1940 if (obj->IsBoolean()) {
1941 return obj->IsTrue();
1942 } else {
1943 ENTER_V8;
1944 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1945 return value->IsTrue();
1946 }
1947}
1948
1949
1950double Value::NumberValue() const {
1951 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1952 LOG_API("NumberValue");
1953 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1954 i::Handle<i::Object> num;
1955 if (obj->IsNumber()) {
1956 num = obj;
1957 } else {
1958 ENTER_V8;
1959 EXCEPTION_PREAMBLE();
1960 num = i::Execution::ToNumber(obj, &has_pending_exception);
1961 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1962 }
1963 return num->Number();
1964}
1965
1966
1967int64_t Value::IntegerValue() const {
1968 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1969 LOG_API("IntegerValue");
1970 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1971 i::Handle<i::Object> num;
1972 if (obj->IsNumber()) {
1973 num = obj;
1974 } else {
1975 ENTER_V8;
1976 EXCEPTION_PREAMBLE();
1977 num = i::Execution::ToInteger(obj, &has_pending_exception);
1978 EXCEPTION_BAILOUT_CHECK(0);
1979 }
1980 if (num->IsSmi()) {
1981 return i::Smi::cast(*num)->value();
1982 } else {
1983 return static_cast<int64_t>(num->Number());
1984 }
1985}
1986
1987
1988Local<Int32> Value::ToInt32() const {
1989 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1990 LOG_API("ToInt32");
1991 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1992 i::Handle<i::Object> num;
1993 if (obj->IsSmi()) {
1994 num = obj;
1995 } else {
1996 ENTER_V8;
1997 EXCEPTION_PREAMBLE();
1998 num = i::Execution::ToInt32(obj, &has_pending_exception);
1999 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2000 }
2001 return Local<Int32>(ToApi<Int32>(num));
2002}
2003
2004
2005Local<Uint32> Value::ToUint32() const {
2006 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2007 LOG_API("ToUInt32");
2008 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2009 i::Handle<i::Object> num;
2010 if (obj->IsSmi()) {
2011 num = obj;
2012 } else {
2013 ENTER_V8;
2014 EXCEPTION_PREAMBLE();
2015 num = i::Execution::ToUint32(obj, &has_pending_exception);
2016 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2017 }
2018 return Local<Uint32>(ToApi<Uint32>(num));
2019}
2020
2021
2022Local<Uint32> Value::ToArrayIndex() const {
2023 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2024 LOG_API("ToArrayIndex");
2025 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2026 if (obj->IsSmi()) {
2027 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2028 return Local<Uint32>();
2029 }
2030 ENTER_V8;
2031 EXCEPTION_PREAMBLE();
2032 i::Handle<i::Object> string_obj =
2033 i::Execution::ToString(obj, &has_pending_exception);
2034 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2035 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2036 uint32_t index;
2037 if (str->AsArrayIndex(&index)) {
2038 i::Handle<i::Object> value;
2039 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2040 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2041 } else {
2042 value = i::Factory::NewNumber(index);
2043 }
2044 return Utils::Uint32ToLocal(value);
2045 }
2046 return Local<Uint32>();
2047}
2048
2049
2050int32_t Value::Int32Value() const {
2051 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2052 LOG_API("Int32Value");
2053 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2054 if (obj->IsSmi()) {
2055 return i::Smi::cast(*obj)->value();
2056 } else {
2057 LOG_API("Int32Value (slow)");
2058 ENTER_V8;
2059 EXCEPTION_PREAMBLE();
2060 i::Handle<i::Object> num =
2061 i::Execution::ToInt32(obj, &has_pending_exception);
2062 EXCEPTION_BAILOUT_CHECK(0);
2063 if (num->IsSmi()) {
2064 return i::Smi::cast(*num)->value();
2065 } else {
2066 return static_cast<int32_t>(num->Number());
2067 }
2068 }
2069}
2070
2071
2072bool Value::Equals(Handle<Value> that) const {
2073 if (IsDeadCheck("v8::Value::Equals()")
2074 || EmptyCheck("v8::Value::Equals()", this)
2075 || EmptyCheck("v8::Value::Equals()", that)) {
2076 return false;
2077 }
2078 LOG_API("Equals");
2079 ENTER_V8;
2080 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2081 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2082 i::Object** args[1] = { other.location() };
2083 EXCEPTION_PREAMBLE();
2084 i::Handle<i::Object> result =
2085 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2086 EXCEPTION_BAILOUT_CHECK(false);
2087 return *result == i::Smi::FromInt(i::EQUAL);
2088}
2089
2090
2091bool Value::StrictEquals(Handle<Value> that) const {
2092 if (IsDeadCheck("v8::Value::StrictEquals()")
2093 || EmptyCheck("v8::Value::StrictEquals()", this)
2094 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2095 return false;
2096 }
2097 LOG_API("StrictEquals");
2098 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2099 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2100 // Must check HeapNumber first, since NaN !== NaN.
2101 if (obj->IsHeapNumber()) {
2102 if (!other->IsNumber()) return false;
2103 double x = obj->Number();
2104 double y = other->Number();
2105 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2106 return x == y && !isnan(x) && !isnan(y);
2107 } else if (*obj == *other) { // Also covers Booleans.
2108 return true;
2109 } else if (obj->IsSmi()) {
2110 return other->IsNumber() && obj->Number() == other->Number();
2111 } else if (obj->IsString()) {
2112 return other->IsString() &&
2113 i::String::cast(*obj)->Equals(i::String::cast(*other));
2114 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2115 return other->IsUndefined() || other->IsUndetectableObject();
2116 } else {
2117 return false;
2118 }
2119}
2120
2121
2122uint32_t Value::Uint32Value() const {
2123 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2124 LOG_API("Uint32Value");
2125 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2126 if (obj->IsSmi()) {
2127 return i::Smi::cast(*obj)->value();
2128 } else {
2129 ENTER_V8;
2130 EXCEPTION_PREAMBLE();
2131 i::Handle<i::Object> num =
2132 i::Execution::ToUint32(obj, &has_pending_exception);
2133 EXCEPTION_BAILOUT_CHECK(0);
2134 if (num->IsSmi()) {
2135 return i::Smi::cast(*num)->value();
2136 } else {
2137 return static_cast<uint32_t>(num->Number());
2138 }
2139 }
2140}
2141
2142
2143bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2144 v8::PropertyAttribute attribs) {
2145 ON_BAILOUT("v8::Object::Set()", return false);
2146 ENTER_V8;
2147 HandleScope scope;
2148 i::Handle<i::Object> self = Utils::OpenHandle(this);
2149 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2150 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2151 EXCEPTION_PREAMBLE();
2152 i::Handle<i::Object> obj = i::SetProperty(
2153 self,
2154 key_obj,
2155 value_obj,
2156 static_cast<PropertyAttributes>(attribs));
2157 has_pending_exception = obj.is_null();
2158 EXCEPTION_BAILOUT_CHECK(false);
2159 return true;
2160}
2161
2162
Steve Block6ded16b2010-05-10 14:33:55 +01002163bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2164 ON_BAILOUT("v8::Object::Set()", return false);
2165 ENTER_V8;
2166 HandleScope scope;
2167 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2168 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2169 EXCEPTION_PREAMBLE();
2170 i::Handle<i::Object> obj = i::SetElement(
2171 self,
2172 index,
2173 value_obj);
2174 has_pending_exception = obj.is_null();
2175 EXCEPTION_BAILOUT_CHECK(false);
2176 return true;
2177}
2178
2179
Steve Blocka7e24c12009-10-30 11:49:00 +00002180bool v8::Object::ForceSet(v8::Handle<Value> key,
2181 v8::Handle<Value> value,
2182 v8::PropertyAttribute attribs) {
2183 ON_BAILOUT("v8::Object::ForceSet()", return false);
2184 ENTER_V8;
2185 HandleScope scope;
2186 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2187 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2188 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2189 EXCEPTION_PREAMBLE();
2190 i::Handle<i::Object> obj = i::ForceSetProperty(
2191 self,
2192 key_obj,
2193 value_obj,
2194 static_cast<PropertyAttributes>(attribs));
2195 has_pending_exception = obj.is_null();
2196 EXCEPTION_BAILOUT_CHECK(false);
2197 return true;
2198}
2199
2200
2201bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2202 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2203 ENTER_V8;
2204 HandleScope scope;
2205 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2206 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2207 EXCEPTION_PREAMBLE();
2208 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2209 has_pending_exception = obj.is_null();
2210 EXCEPTION_BAILOUT_CHECK(false);
2211 return obj->IsTrue();
2212}
2213
2214
2215Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2216 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2217 ENTER_V8;
2218 i::Handle<i::Object> self = Utils::OpenHandle(this);
2219 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2220 EXCEPTION_PREAMBLE();
2221 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2222 has_pending_exception = result.is_null();
2223 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2224 return Utils::ToLocal(result);
2225}
2226
2227
Steve Block6ded16b2010-05-10 14:33:55 +01002228Local<Value> v8::Object::Get(uint32_t index) {
2229 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2230 ENTER_V8;
2231 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2232 EXCEPTION_PREAMBLE();
2233 i::Handle<i::Object> result = i::GetElement(self, index);
2234 has_pending_exception = result.is_null();
2235 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2236 return Utils::ToLocal(result);
2237}
2238
2239
Steve Blocka7e24c12009-10-30 11:49:00 +00002240Local<Value> v8::Object::GetPrototype() {
2241 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2242 ENTER_V8;
2243 i::Handle<i::Object> self = Utils::OpenHandle(this);
2244 i::Handle<i::Object> result = i::GetPrototype(self);
2245 return Utils::ToLocal(result);
2246}
2247
2248
Andrei Popescu402d9372010-02-26 13:31:12 +00002249bool v8::Object::SetPrototype(Handle<Value> value) {
2250 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2251 ENTER_V8;
2252 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2253 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2254 EXCEPTION_PREAMBLE();
2255 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2256 has_pending_exception = result.is_null();
2257 EXCEPTION_BAILOUT_CHECK(false);
2258 return true;
2259}
2260
2261
Steve Blocka7e24c12009-10-30 11:49:00 +00002262Local<Object> v8::Object::FindInstanceInPrototypeChain(
2263 v8::Handle<FunctionTemplate> tmpl) {
2264 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2265 return Local<v8::Object>());
2266 ENTER_V8;
2267 i::JSObject* object = *Utils::OpenHandle(this);
2268 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2269 while (!object->IsInstanceOf(tmpl_info)) {
2270 i::Object* prototype = object->GetPrototype();
2271 if (!prototype->IsJSObject()) return Local<Object>();
2272 object = i::JSObject::cast(prototype);
2273 }
2274 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2275}
2276
2277
2278Local<Array> v8::Object::GetPropertyNames() {
2279 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2280 ENTER_V8;
2281 v8::HandleScope scope;
2282 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2283 i::Handle<i::FixedArray> value =
2284 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2285 // Because we use caching to speed up enumeration it is important
2286 // to never change the result of the basic enumeration function so
2287 // we clone the result.
2288 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2289 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2290 return scope.Close(Utils::ToLocal(result));
2291}
2292
2293
2294Local<String> v8::Object::ObjectProtoToString() {
2295 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2296 ENTER_V8;
2297 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2298
2299 i::Handle<i::Object> name(self->class_name());
2300
2301 // Native implementation of Object.prototype.toString (v8natives.js):
2302 // var c = %ClassOf(this);
2303 // if (c === 'Arguments') c = 'Object';
2304 // return "[object " + c + "]";
2305
2306 if (!name->IsString()) {
2307 return v8::String::New("[object ]");
2308
2309 } else {
2310 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2311 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2312 return v8::String::New("[object Object]");
2313
2314 } else {
2315 const char* prefix = "[object ";
2316 Local<String> str = Utils::ToLocal(class_name);
2317 const char* postfix = "]";
2318
Steve Blockd0582a62009-12-15 09:54:21 +00002319 int prefix_len = i::StrLength(prefix);
2320 int str_len = str->Length();
2321 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002322
Steve Blockd0582a62009-12-15 09:54:21 +00002323 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002324 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002325
2326 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002327 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002328 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2329 ptr += prefix_len;
2330
2331 // Write real content.
2332 str->WriteAscii(ptr, 0, str_len);
2333 ptr += str_len;
2334
2335 // Write postfix.
2336 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2337
2338 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002339 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002340 return result;
2341 }
2342 }
2343}
2344
2345
2346bool v8::Object::Delete(v8::Handle<String> key) {
2347 ON_BAILOUT("v8::Object::Delete()", return false);
2348 ENTER_V8;
2349 HandleScope scope;
2350 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2351 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2352 return i::DeleteProperty(self, key_obj)->IsTrue();
2353}
2354
2355
2356bool v8::Object::Has(v8::Handle<String> key) {
2357 ON_BAILOUT("v8::Object::Has()", return false);
2358 ENTER_V8;
2359 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2360 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2361 return self->HasProperty(*key_obj);
2362}
2363
2364
2365bool v8::Object::Delete(uint32_t index) {
2366 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2367 ENTER_V8;
2368 HandleScope scope;
2369 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2370 return i::DeleteElement(self, index)->IsTrue();
2371}
2372
2373
2374bool v8::Object::Has(uint32_t index) {
2375 ON_BAILOUT("v8::Object::HasProperty()", return false);
2376 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2377 return self->HasElement(index);
2378}
2379
2380
Leon Clarkef7060e22010-06-03 12:02:55 +01002381bool Object::SetAccessor(Handle<String> name,
2382 AccessorGetter getter,
2383 AccessorSetter setter,
2384 v8::Handle<Value> data,
2385 AccessControl settings,
2386 PropertyAttribute attributes) {
2387 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2388 ENTER_V8;
2389 HandleScope scope;
2390 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2391 getter, setter, data,
2392 settings, attributes);
2393 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2394 return !result.is_null() && !result->IsUndefined();
2395}
2396
2397
Steve Blocka7e24c12009-10-30 11:49:00 +00002398bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2399 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2400 return Utils::OpenHandle(this)->HasRealNamedProperty(
2401 *Utils::OpenHandle(*key));
2402}
2403
2404
2405bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2406 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2407 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2408}
2409
2410
2411bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2412 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2413 ENTER_V8;
2414 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2415 *Utils::OpenHandle(*key));
2416}
2417
2418
2419bool v8::Object::HasNamedLookupInterceptor() {
2420 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2421 return Utils::OpenHandle(this)->HasNamedInterceptor();
2422}
2423
2424
2425bool v8::Object::HasIndexedLookupInterceptor() {
2426 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2427 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2428}
2429
2430
2431Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2432 Handle<String> key) {
2433 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2434 return Local<Value>());
2435 ENTER_V8;
2436 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2437 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2438 i::LookupResult lookup;
2439 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002440 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002441 PropertyAttributes attributes;
2442 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2443 &lookup,
2444 *key_obj,
2445 &attributes));
2446 return Utils::ToLocal(result);
2447 }
2448 return Local<Value>(); // No real property was found in prototype chain.
2449}
2450
2451
2452Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2453 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2454 ENTER_V8;
2455 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2456 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2457 i::LookupResult lookup;
2458 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002459 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002460 PropertyAttributes attributes;
2461 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2462 &lookup,
2463 *key_obj,
2464 &attributes));
2465 return Utils::ToLocal(result);
2466 }
2467 return Local<Value>(); // No real property was found in prototype chain.
2468}
2469
2470
2471// Turns on access checks by copying the map and setting the check flag.
2472// Because the object gets a new map, existing inline cache caching
2473// the old map of this object will fail.
2474void v8::Object::TurnOnAccessCheck() {
2475 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2476 ENTER_V8;
2477 HandleScope scope;
2478 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2479
2480 i::Handle<i::Map> new_map =
2481 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2482 new_map->set_is_access_check_needed(true);
2483 obj->set_map(*new_map);
2484}
2485
2486
2487bool v8::Object::IsDirty() {
2488 return Utils::OpenHandle(this)->IsDirty();
2489}
2490
2491
2492Local<v8::Object> v8::Object::Clone() {
2493 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2494 ENTER_V8;
2495 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2496 EXCEPTION_PREAMBLE();
2497 i::Handle<i::JSObject> result = i::Copy(self);
2498 has_pending_exception = result.is_null();
2499 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2500 return Utils::ToLocal(result);
2501}
2502
2503
2504int v8::Object::GetIdentityHash() {
2505 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2506 ENTER_V8;
2507 HandleScope scope;
2508 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2509 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2510 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2511 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2512 int hash_value;
2513 if (hash->IsSmi()) {
2514 hash_value = i::Smi::cast(*hash)->value();
2515 } else {
2516 int attempts = 0;
2517 do {
2518 // Generate a random 32-bit hash value but limit range to fit
2519 // within a smi.
2520 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2521 attempts++;
2522 } while (hash_value == 0 && attempts < 30);
2523 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2524 i::SetProperty(hidden_props,
2525 hash_symbol,
2526 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2527 static_cast<PropertyAttributes>(None));
2528 }
2529 return hash_value;
2530}
2531
2532
2533bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2534 v8::Handle<v8::Value> value) {
2535 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2536 ENTER_V8;
2537 HandleScope scope;
2538 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2539 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2540 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2541 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2542 EXCEPTION_PREAMBLE();
2543 i::Handle<i::Object> obj = i::SetProperty(
2544 hidden_props,
2545 key_obj,
2546 value_obj,
2547 static_cast<PropertyAttributes>(None));
2548 has_pending_exception = obj.is_null();
2549 EXCEPTION_BAILOUT_CHECK(false);
2550 return true;
2551}
2552
2553
2554v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2555 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2556 ENTER_V8;
2557 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2558 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2559 if (hidden_props->IsUndefined()) {
2560 return v8::Local<v8::Value>();
2561 }
2562 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2563 EXCEPTION_PREAMBLE();
2564 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2565 has_pending_exception = result.is_null();
2566 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2567 if (result->IsUndefined()) {
2568 return v8::Local<v8::Value>();
2569 }
2570 return Utils::ToLocal(result);
2571}
2572
2573
2574bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2575 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2576 ENTER_V8;
2577 HandleScope scope;
2578 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2579 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2580 if (hidden_props->IsUndefined()) {
2581 return true;
2582 }
2583 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2584 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2585 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2586}
2587
2588
2589void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2590 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2591 ENTER_V8;
2592 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002593 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002594 "v8::Object::SetIndexedPropertiesToPixelData()",
2595 "length exceeds max acceptable value")) {
2596 return;
2597 }
2598 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2599 if (!ApiCheck(!self->IsJSArray(),
2600 "v8::Object::SetIndexedPropertiesToPixelData()",
2601 "JSArray is not supported")) {
2602 return;
2603 }
2604 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2605 self->set_elements(*pixels);
2606}
2607
2608
Steve Block3ce2e202009-11-05 08:53:23 +00002609void v8::Object::SetIndexedPropertiesToExternalArrayData(
2610 void* data,
2611 ExternalArrayType array_type,
2612 int length) {
2613 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2614 ENTER_V8;
2615 HandleScope scope;
2616 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2617 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2618 "length exceeds max acceptable value")) {
2619 return;
2620 }
2621 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2622 if (!ApiCheck(!self->IsJSArray(),
2623 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2624 "JSArray is not supported")) {
2625 return;
2626 }
2627 i::Handle<i::ExternalArray> array =
2628 i::Factory::NewExternalArray(length, array_type, data);
2629 self->set_elements(*array);
2630}
2631
2632
Steve Blocka7e24c12009-10-30 11:49:00 +00002633Local<v8::Object> Function::NewInstance() const {
2634 return NewInstance(0, NULL);
2635}
2636
2637
2638Local<v8::Object> Function::NewInstance(int argc,
2639 v8::Handle<v8::Value> argv[]) const {
2640 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2641 LOG_API("Function::NewInstance");
2642 ENTER_V8;
2643 HandleScope scope;
2644 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2645 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2646 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2647 EXCEPTION_PREAMBLE();
2648 i::Handle<i::Object> returned =
2649 i::Execution::New(function, argc, args, &has_pending_exception);
2650 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2651 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2652}
2653
2654
2655Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2656 v8::Handle<v8::Value> argv[]) {
2657 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2658 LOG_API("Function::Call");
2659 ENTER_V8;
2660 i::Object* raw_result = NULL;
2661 {
2662 HandleScope scope;
2663 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2664 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2665 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2666 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2667 EXCEPTION_PREAMBLE();
2668 i::Handle<i::Object> returned =
2669 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2670 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2671 raw_result = *returned;
2672 }
2673 i::Handle<i::Object> result(raw_result);
2674 return Utils::ToLocal(result);
2675}
2676
2677
2678void Function::SetName(v8::Handle<v8::String> name) {
2679 ENTER_V8;
2680 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2681 func->shared()->set_name(*Utils::OpenHandle(*name));
2682}
2683
2684
2685Handle<Value> Function::GetName() const {
2686 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2687 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2688}
2689
2690
Andrei Popescu402d9372010-02-26 13:31:12 +00002691ScriptOrigin Function::GetScriptOrigin() const {
2692 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2693 if (func->shared()->script()->IsScript()) {
2694 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2695 v8::ScriptOrigin origin(
2696 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2697 v8::Integer::New(script->line_offset()->value()),
2698 v8::Integer::New(script->column_offset()->value()));
2699 return origin;
2700 }
2701 return v8::ScriptOrigin(Handle<Value>());
2702}
2703
2704
2705const int Function::kLineOffsetNotFound = -1;
2706
2707
2708int Function::GetScriptLineNumber() const {
2709 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2710 if (func->shared()->script()->IsScript()) {
2711 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2712 return i::GetScriptLineNumber(script, func->shared()->start_position());
2713 }
2714 return kLineOffsetNotFound;
2715}
2716
2717
2718namespace {
2719
2720// Tracks string usage to help make better decisions when
2721// externalizing strings.
2722//
2723// Implementation note: internally this class only tracks fresh
2724// strings and keeps a single use counter for them.
2725class StringTracker {
2726 public:
2727 // Records that the given string's characters were copied to some
2728 // external buffer. If this happens often we should honor
2729 // externalization requests for the string.
2730 static void RecordWrite(i::Handle<i::String> string) {
2731 i::Address address = reinterpret_cast<i::Address>(*string);
2732 i::Address top = i::Heap::NewSpaceTop();
2733 if (IsFreshString(address, top)) {
2734 IncrementUseCount(top);
2735 }
2736 }
2737
2738 // Estimates freshness and use frequency of the given string based
2739 // on how close it is to the new space top and the recorded usage
2740 // history.
2741 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2742 i::Address address = reinterpret_cast<i::Address>(*string);
2743 i::Address top = i::Heap::NewSpaceTop();
2744 return IsFreshString(address, top) && IsUseCountLow(top);
2745 }
2746
2747 private:
2748 static inline bool IsFreshString(i::Address string, i::Address top) {
2749 return top - kFreshnessLimit <= string && string <= top;
2750 }
2751
2752 static inline bool IsUseCountLow(i::Address top) {
2753 if (last_top_ != top) return true;
2754 return use_count_ < kUseLimit;
2755 }
2756
2757 static inline void IncrementUseCount(i::Address top) {
2758 if (last_top_ != top) {
2759 use_count_ = 0;
2760 last_top_ = top;
2761 }
2762 ++use_count_;
2763 }
2764
2765 // How close to the new space top a fresh string has to be.
2766 static const int kFreshnessLimit = 1024;
2767
2768 // The number of uses required to consider a string useful.
2769 static const int kUseLimit = 32;
2770
2771 // Single use counter shared by all fresh strings.
2772 static int use_count_;
2773
2774 // Last new space top when the use count above was valid.
2775 static i::Address last_top_;
2776};
2777
2778int StringTracker::use_count_ = 0;
2779i::Address StringTracker::last_top_ = NULL;
2780
2781} // namespace
2782
2783
Steve Blocka7e24c12009-10-30 11:49:00 +00002784int String::Length() const {
2785 if (IsDeadCheck("v8::String::Length()")) return 0;
2786 return Utils::OpenHandle(this)->length();
2787}
2788
2789
2790int String::Utf8Length() const {
2791 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2792 return Utils::OpenHandle(this)->Utf8Length();
2793}
2794
2795
Steve Block6ded16b2010-05-10 14:33:55 +01002796int String::WriteUtf8(char* buffer,
2797 int capacity,
2798 int* nchars_ref,
2799 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002800 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2801 LOG_API("String::WriteUtf8");
2802 ENTER_V8;
2803 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002804 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002805 if (hints & HINT_MANY_WRITES_EXPECTED) {
2806 // Flatten the string for efficiency. This applies whether we are
2807 // using StringInputBuffer or Get(i) to access the characters.
2808 str->TryFlatten();
2809 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002810 write_input_buffer.Reset(0, *str);
2811 int len = str->length();
2812 // Encode the first K - 3 bytes directly into the buffer since we
2813 // know there's room for them. If no capacity is given we copy all
2814 // of them here.
2815 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2816 int i;
2817 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002818 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002819 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2820 i::uc32 c = write_input_buffer.GetNext();
2821 int written = unibrow::Utf8::Encode(buffer + pos, c);
2822 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002823 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002824 }
2825 if (i < len) {
2826 // For the last characters we need to check the length for each one
2827 // because they may be longer than the remaining space in the
2828 // buffer.
2829 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2830 for (; i < len && pos < capacity; i++) {
2831 i::uc32 c = write_input_buffer.GetNext();
2832 int written = unibrow::Utf8::Encode(intermediate, c);
2833 if (pos + written <= capacity) {
2834 for (int j = 0; j < written; j++)
2835 buffer[pos + j] = intermediate[j];
2836 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002837 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002838 } else {
2839 // We've reached the end of the buffer
2840 break;
2841 }
2842 }
2843 }
Steve Block6ded16b2010-05-10 14:33:55 +01002844 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002845 if (i == len && (capacity == -1 || pos < capacity))
2846 buffer[pos++] = '\0';
2847 return pos;
2848}
2849
2850
Steve Block6ded16b2010-05-10 14:33:55 +01002851int String::WriteAscii(char* buffer,
2852 int start,
2853 int length,
2854 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002855 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2856 LOG_API("String::WriteAscii");
2857 ENTER_V8;
2858 ASSERT(start >= 0 && length >= -1);
2859 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002860 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002861 if (hints & HINT_MANY_WRITES_EXPECTED) {
2862 // Flatten the string for efficiency. This applies whether we are
2863 // using StringInputBuffer or Get(i) to access the characters.
2864 str->TryFlatten();
2865 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002866 int end = length;
2867 if ( (length == -1) || (length > str->length() - start) )
2868 end = str->length() - start;
2869 if (end < 0) return 0;
2870 write_input_buffer.Reset(start, *str);
2871 int i;
2872 for (i = 0; i < end; i++) {
2873 char c = static_cast<char>(write_input_buffer.GetNext());
2874 if (c == '\0') c = ' ';
2875 buffer[i] = c;
2876 }
2877 if (length == -1 || i < length)
2878 buffer[i] = '\0';
2879 return i;
2880}
2881
2882
Steve Block6ded16b2010-05-10 14:33:55 +01002883int String::Write(uint16_t* buffer,
2884 int start,
2885 int length,
2886 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002887 if (IsDeadCheck("v8::String::Write()")) return 0;
2888 LOG_API("String::Write");
2889 ENTER_V8;
2890 ASSERT(start >= 0 && length >= -1);
2891 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002892 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002893 if (hints & HINT_MANY_WRITES_EXPECTED) {
2894 // Flatten the string for efficiency. This applies whether we are
2895 // using StringInputBuffer or Get(i) to access the characters.
2896 str->TryFlatten();
2897 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002898 int end = length;
2899 if ( (length == -1) || (length > str->length() - start) )
2900 end = str->length() - start;
2901 if (end < 0) return 0;
2902 i::String::WriteToFlat(*str, buffer, start, end);
2903 if (length == -1 || end < length)
2904 buffer[end] = '\0';
2905 return end;
2906}
2907
2908
2909bool v8::String::IsExternal() const {
2910 EnsureInitialized("v8::String::IsExternal()");
2911 i::Handle<i::String> str = Utils::OpenHandle(this);
2912 return i::StringShape(*str).IsExternalTwoByte();
2913}
2914
2915
2916bool v8::String::IsExternalAscii() const {
2917 EnsureInitialized("v8::String::IsExternalAscii()");
2918 i::Handle<i::String> str = Utils::OpenHandle(this);
2919 return i::StringShape(*str).IsExternalAscii();
2920}
2921
2922
2923void v8::String::VerifyExternalStringResource(
2924 v8::String::ExternalStringResource* value) const {
2925 i::Handle<i::String> str = Utils::OpenHandle(this);
2926 v8::String::ExternalStringResource* expected;
2927 if (i::StringShape(*str).IsExternalTwoByte()) {
2928 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2929 expected = reinterpret_cast<ExternalStringResource*>(resource);
2930 } else {
2931 expected = NULL;
2932 }
2933 CHECK_EQ(expected, value);
2934}
2935
2936
2937v8::String::ExternalAsciiStringResource*
2938 v8::String::GetExternalAsciiStringResource() const {
2939 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2940 i::Handle<i::String> str = Utils::OpenHandle(this);
2941 if (i::StringShape(*str).IsExternalAscii()) {
2942 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2943 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2944 } else {
2945 return NULL;
2946 }
2947}
2948
2949
2950double Number::Value() const {
2951 if (IsDeadCheck("v8::Number::Value()")) return 0;
2952 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2953 return obj->Number();
2954}
2955
2956
2957bool Boolean::Value() const {
2958 if (IsDeadCheck("v8::Boolean::Value()")) return false;
2959 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2960 return obj->IsTrue();
2961}
2962
2963
2964int64_t Integer::Value() const {
2965 if (IsDeadCheck("v8::Integer::Value()")) return 0;
2966 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2967 if (obj->IsSmi()) {
2968 return i::Smi::cast(*obj)->value();
2969 } else {
2970 return static_cast<int64_t>(obj->Number());
2971 }
2972}
2973
2974
2975int32_t Int32::Value() const {
2976 if (IsDeadCheck("v8::Int32::Value()")) return 0;
2977 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2978 if (obj->IsSmi()) {
2979 return i::Smi::cast(*obj)->value();
2980 } else {
2981 return static_cast<int32_t>(obj->Number());
2982 }
2983}
2984
2985
Steve Block6ded16b2010-05-10 14:33:55 +01002986uint32_t Uint32::Value() const {
2987 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
2988 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2989 if (obj->IsSmi()) {
2990 return i::Smi::cast(*obj)->value();
2991 } else {
2992 return static_cast<uint32_t>(obj->Number());
2993 }
2994}
2995
2996
Steve Blocka7e24c12009-10-30 11:49:00 +00002997int v8::Object::InternalFieldCount() {
2998 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2999 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3000 return obj->GetInternalFieldCount();
3001}
3002
3003
3004Local<Value> v8::Object::CheckedGetInternalField(int index) {
3005 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3006 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3007 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3008 "v8::Object::GetInternalField()",
3009 "Reading internal field out of bounds")) {
3010 return Local<Value>();
3011 }
3012 i::Handle<i::Object> value(obj->GetInternalField(index));
3013 Local<Value> result = Utils::ToLocal(value);
3014#ifdef DEBUG
3015 Local<Value> unchecked = UncheckedGetInternalField(index);
3016 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3017#endif
3018 return result;
3019}
3020
3021
3022void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3023 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3024 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3025 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3026 "v8::Object::SetInternalField()",
3027 "Writing internal field out of bounds")) {
3028 return;
3029 }
3030 ENTER_V8;
3031 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3032 obj->SetInternalField(index, *val);
3033}
3034
3035
3036void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003037 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003038 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3039 if (as_object->IsSmi()) {
3040 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3041 return;
3042 }
3043 HandleScope scope;
3044 i::Handle<i::Proxy> proxy =
3045 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3046 if (!proxy.is_null())
3047 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003048}
3049
3050
3051// --- E n v i r o n m e n t ---
3052
3053bool v8::V8::Initialize() {
3054 if (i::V8::IsRunning()) return true;
3055 ENTER_V8;
3056 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003057 if (i::Snapshot::Initialize()) return true;
3058 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003059}
3060
3061
3062bool v8::V8::Dispose() {
3063 i::V8::TearDown();
3064 return true;
3065}
3066
3067
Steve Block3ce2e202009-11-05 08:53:23 +00003068HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3069
3070
3071void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3072 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3073 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3074}
3075
3076
3077bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003078 // Returning true tells the caller that it need not
3079 // continue to call IdleNotification.
3080 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003081 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003082}
3083
3084
3085void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003086 if (!i::V8::IsRunning()) return;
3087 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003088}
3089
3090
Steve Block6ded16b2010-05-10 14:33:55 +01003091int v8::V8::ContextDisposedNotification() {
3092 if (!i::V8::IsRunning()) return 0;
3093 return i::Heap::NotifyContextDisposed();
3094}
3095
3096
Steve Blocka7e24c12009-10-30 11:49:00 +00003097const char* v8::V8::GetVersion() {
3098 static v8::internal::EmbeddedVector<char, 128> buffer;
3099 v8::internal::Version::GetString(buffer);
3100 return buffer.start();
3101}
3102
3103
3104static i::Handle<i::FunctionTemplateInfo>
3105 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3106 if (templ->constructor()->IsUndefined()) {
3107 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3108 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3109 templ->set_constructor(*Utils::OpenHandle(*constructor));
3110 }
3111 return i::Handle<i::FunctionTemplateInfo>(
3112 i::FunctionTemplateInfo::cast(templ->constructor()));
3113}
3114
3115
3116Persistent<Context> v8::Context::New(
3117 v8::ExtensionConfiguration* extensions,
3118 v8::Handle<ObjectTemplate> global_template,
3119 v8::Handle<Value> global_object) {
3120 EnsureInitialized("v8::Context::New()");
3121 LOG_API("Context::New");
3122 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3123
3124 // Enter V8 via an ENTER_V8 scope.
3125 i::Handle<i::Context> env;
3126 {
3127 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003128 v8::Handle<ObjectTemplate> proxy_template = global_template;
3129 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3130 i::Handle<i::FunctionTemplateInfo> global_constructor;
3131
3132 if (!global_template.IsEmpty()) {
3133 // Make sure that the global_template has a constructor.
3134 global_constructor =
3135 EnsureConstructor(Utils::OpenHandle(*global_template));
3136
3137 // Create a fresh template for the global proxy object.
3138 proxy_template = ObjectTemplate::New();
3139 proxy_constructor =
3140 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3141
3142 // Set the global template to be the prototype template of
3143 // global proxy template.
3144 proxy_constructor->set_prototype_template(
3145 *Utils::OpenHandle(*global_template));
3146
3147 // Migrate security handlers from global_template to
3148 // proxy_template. Temporarily removing access check
3149 // information from the global template.
3150 if (!global_constructor->access_check_info()->IsUndefined()) {
3151 proxy_constructor->set_access_check_info(
3152 global_constructor->access_check_info());
3153 proxy_constructor->set_needs_access_check(
3154 global_constructor->needs_access_check());
3155 global_constructor->set_needs_access_check(false);
3156 global_constructor->set_access_check_info(i::Heap::undefined_value());
3157 }
3158 }
3159
3160 // Create the environment.
3161 env = i::Bootstrapper::CreateEnvironment(
3162 Utils::OpenHandle(*global_object),
3163 proxy_template,
3164 extensions);
3165
3166 // Restore the access check info on the global template.
3167 if (!global_template.IsEmpty()) {
3168 ASSERT(!global_constructor.is_null());
3169 ASSERT(!proxy_constructor.is_null());
3170 global_constructor->set_access_check_info(
3171 proxy_constructor->access_check_info());
3172 global_constructor->set_needs_access_check(
3173 proxy_constructor->needs_access_check());
3174 }
3175 }
3176 // Leave V8.
3177
3178 if (env.is_null())
3179 return Persistent<Context>();
3180 return Persistent<Context>(Utils::ToLocal(env));
3181}
3182
3183
3184void v8::Context::SetSecurityToken(Handle<Value> token) {
3185 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3186 ENTER_V8;
3187 i::Handle<i::Context> env = Utils::OpenHandle(this);
3188 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3189 env->set_security_token(*token_handle);
3190}
3191
3192
3193void v8::Context::UseDefaultSecurityToken() {
3194 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3195 ENTER_V8;
3196 i::Handle<i::Context> env = Utils::OpenHandle(this);
3197 env->set_security_token(env->global());
3198}
3199
3200
3201Handle<Value> v8::Context::GetSecurityToken() {
3202 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3203 i::Handle<i::Context> env = Utils::OpenHandle(this);
3204 i::Object* security_token = env->security_token();
3205 i::Handle<i::Object> token_handle(security_token);
3206 return Utils::ToLocal(token_handle);
3207}
3208
3209
3210bool Context::HasOutOfMemoryException() {
3211 i::Handle<i::Context> env = Utils::OpenHandle(this);
3212 return env->has_out_of_memory();
3213}
3214
3215
3216bool Context::InContext() {
3217 return i::Top::context() != NULL;
3218}
3219
3220
3221v8::Local<v8::Context> Context::GetEntered() {
3222 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3223 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3224 if (last.is_null()) return Local<Context>();
3225 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3226 return Utils::ToLocal(context);
3227}
3228
3229
3230v8::Local<v8::Context> Context::GetCurrent() {
3231 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003232 i::Handle<i::Object> current = i::Top::global_context();
3233 if (current.is_null()) return Local<Context>();
3234 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003235 return Utils::ToLocal(context);
3236}
3237
3238
3239v8::Local<v8::Context> Context::GetCalling() {
3240 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3241 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3242 if (calling.is_null()) return Local<Context>();
3243 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3244 return Utils::ToLocal(context);
3245}
3246
3247
3248v8::Local<v8::Object> Context::Global() {
3249 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3250 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3251 i::Handle<i::Context> context =
3252 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3253 i::Handle<i::Object> global(context->global_proxy());
3254 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3255}
3256
3257
3258void Context::DetachGlobal() {
3259 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3260 ENTER_V8;
3261 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3262 i::Handle<i::Context> context =
3263 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3264 i::Bootstrapper::DetachGlobal(context);
3265}
3266
3267
Andrei Popescu74b3c142010-03-29 12:03:09 +01003268void Context::ReattachGlobal(Handle<Object> global_object) {
3269 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3270 ENTER_V8;
3271 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3272 i::Handle<i::Context> context =
3273 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3274 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3275}
3276
3277
Steve Blocka7e24c12009-10-30 11:49:00 +00003278Local<v8::Object> ObjectTemplate::NewInstance() {
3279 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3280 LOG_API("ObjectTemplate::NewInstance");
3281 ENTER_V8;
3282 EXCEPTION_PREAMBLE();
3283 i::Handle<i::Object> obj =
3284 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3285 &has_pending_exception);
3286 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3287 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3288}
3289
3290
3291Local<v8::Function> FunctionTemplate::GetFunction() {
3292 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3293 return Local<v8::Function>());
3294 LOG_API("FunctionTemplate::GetFunction");
3295 ENTER_V8;
3296 EXCEPTION_PREAMBLE();
3297 i::Handle<i::Object> obj =
3298 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3299 &has_pending_exception);
3300 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3301 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3302}
3303
3304
3305bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3306 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3307 i::Object* obj = *Utils::OpenHandle(*value);
3308 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3309}
3310
3311
3312static Local<External> ExternalNewImpl(void* data) {
3313 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3314}
3315
3316static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3317 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3318}
3319
3320
Steve Blocka7e24c12009-10-30 11:49:00 +00003321Local<Value> v8::External::Wrap(void* data) {
3322 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3323 LOG_API("External::Wrap");
3324 EnsureInitialized("v8::External::Wrap()");
3325 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003326 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3327 if (as_object->IsSmi()) {
3328 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003329 }
3330 return ExternalNewImpl(data);
3331}
3332
3333
Steve Block3ce2e202009-11-05 08:53:23 +00003334void* v8::Object::SlowGetPointerFromInternalField(int index) {
3335 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3336 i::Object* value = obj->GetInternalField(index);
3337 if (value->IsSmi()) {
3338 return value;
3339 } else if (value->IsProxy()) {
3340 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3341 } else {
3342 return NULL;
3343 }
3344}
3345
3346
Steve Blocka7e24c12009-10-30 11:49:00 +00003347void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3348 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3349 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3350 void* result;
3351 if (obj->IsSmi()) {
3352 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003353 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003354 } else if (obj->IsProxy()) {
3355 result = ExternalValueImpl(obj);
3356 } else {
3357 result = NULL;
3358 }
3359 ASSERT_EQ(result, QuickUnwrap(wrapper));
3360 return result;
3361}
3362
3363
3364Local<External> v8::External::New(void* data) {
3365 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3366 LOG_API("External::New");
3367 EnsureInitialized("v8::External::New()");
3368 ENTER_V8;
3369 return ExternalNewImpl(data);
3370}
3371
3372
3373void* External::Value() const {
3374 if (IsDeadCheck("v8::External::Value()")) return 0;
3375 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3376 return ExternalValueImpl(obj);
3377}
3378
3379
3380Local<String> v8::String::Empty() {
3381 EnsureInitialized("v8::String::Empty()");
3382 LOG_API("String::Empty()");
3383 return Utils::ToLocal(i::Factory::empty_symbol());
3384}
3385
3386
3387Local<String> v8::String::New(const char* data, int length) {
3388 EnsureInitialized("v8::String::New()");
3389 LOG_API("String::New(char)");
3390 if (length == 0) return Empty();
3391 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003392 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003393 i::Handle<i::String> result =
3394 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3395 return Utils::ToLocal(result);
3396}
3397
3398
Steve Block3ce2e202009-11-05 08:53:23 +00003399Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3400 EnsureInitialized("v8::String::New()");
3401 LOG_API("String::New(char)");
3402 ENTER_V8;
3403 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3404 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3405 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3406 right_string);
3407 return Utils::ToLocal(result);
3408}
3409
3410
Steve Blocka7e24c12009-10-30 11:49:00 +00003411Local<String> v8::String::NewUndetectable(const char* data, int length) {
3412 EnsureInitialized("v8::String::NewUndetectable()");
3413 LOG_API("String::NewUndetectable(char)");
3414 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003415 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003416 i::Handle<i::String> result =
3417 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3418 result->MarkAsUndetectable();
3419 return Utils::ToLocal(result);
3420}
3421
3422
3423static int TwoByteStringLength(const uint16_t* data) {
3424 int length = 0;
3425 while (data[length] != '\0') length++;
3426 return length;
3427}
3428
3429
3430Local<String> v8::String::New(const uint16_t* data, int length) {
3431 EnsureInitialized("v8::String::New()");
3432 LOG_API("String::New(uint16_)");
3433 if (length == 0) return Empty();
3434 ENTER_V8;
3435 if (length == -1) length = TwoByteStringLength(data);
3436 i::Handle<i::String> result =
3437 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3438 return Utils::ToLocal(result);
3439}
3440
3441
3442Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3443 EnsureInitialized("v8::String::NewUndetectable()");
3444 LOG_API("String::NewUndetectable(uint16_)");
3445 ENTER_V8;
3446 if (length == -1) length = TwoByteStringLength(data);
3447 i::Handle<i::String> result =
3448 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3449 result->MarkAsUndetectable();
3450 return Utils::ToLocal(result);
3451}
3452
3453
3454i::Handle<i::String> NewExternalStringHandle(
3455 v8::String::ExternalStringResource* resource) {
3456 i::Handle<i::String> result =
3457 i::Factory::NewExternalStringFromTwoByte(resource);
3458 return result;
3459}
3460
3461
3462i::Handle<i::String> NewExternalAsciiStringHandle(
3463 v8::String::ExternalAsciiStringResource* resource) {
3464 i::Handle<i::String> result =
3465 i::Factory::NewExternalStringFromAscii(resource);
3466 return result;
3467}
3468
3469
Steve Blocka7e24c12009-10-30 11:49:00 +00003470Local<String> v8::String::NewExternal(
3471 v8::String::ExternalStringResource* resource) {
3472 EnsureInitialized("v8::String::NewExternal()");
3473 LOG_API("String::NewExternal");
3474 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003475 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003476 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003477 return Utils::ToLocal(result);
3478}
3479
3480
3481bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3482 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3483 if (this->IsExternal()) return false; // Already an external string.
3484 ENTER_V8;
3485 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003486 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003487 bool result = obj->MakeExternal(resource);
3488 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003489 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003490 }
3491 return result;
3492}
3493
3494
3495Local<String> v8::String::NewExternal(
3496 v8::String::ExternalAsciiStringResource* resource) {
3497 EnsureInitialized("v8::String::NewExternal()");
3498 LOG_API("String::NewExternal");
3499 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003500 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003501 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003502 return Utils::ToLocal(result);
3503}
3504
3505
3506bool v8::String::MakeExternal(
3507 v8::String::ExternalAsciiStringResource* resource) {
3508 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3509 if (this->IsExternal()) return false; // Already an external string.
3510 ENTER_V8;
3511 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003512 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003513 bool result = obj->MakeExternal(resource);
3514 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003515 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003516 }
3517 return result;
3518}
3519
3520
3521bool v8::String::CanMakeExternal() {
3522 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3523 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003524 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003525 int size = obj->Size(); // Byte size of the original string.
3526 if (size < i::ExternalString::kSize)
3527 return false;
3528 i::StringShape shape(*obj);
3529 return !shape.IsExternal();
3530}
3531
3532
3533Local<v8::Object> v8::Object::New() {
3534 EnsureInitialized("v8::Object::New()");
3535 LOG_API("Object::New");
3536 ENTER_V8;
3537 i::Handle<i::JSObject> obj =
3538 i::Factory::NewJSObject(i::Top::object_function());
3539 return Utils::ToLocal(obj);
3540}
3541
3542
3543Local<v8::Value> v8::Date::New(double time) {
3544 EnsureInitialized("v8::Date::New()");
3545 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003546 if (isnan(time)) {
3547 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3548 time = i::OS::nan_value();
3549 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003550 ENTER_V8;
3551 EXCEPTION_PREAMBLE();
3552 i::Handle<i::Object> obj =
3553 i::Execution::NewDate(time, &has_pending_exception);
3554 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3555 return Utils::ToLocal(obj);
3556}
3557
3558
3559double v8::Date::NumberValue() const {
3560 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3561 LOG_API("Date::NumberValue");
3562 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3563 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3564 return jsvalue->value()->Number();
3565}
3566
3567
3568Local<v8::Array> v8::Array::New(int length) {
3569 EnsureInitialized("v8::Array::New()");
3570 LOG_API("Array::New");
3571 ENTER_V8;
3572 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3573 return Utils::ToLocal(obj);
3574}
3575
3576
3577uint32_t v8::Array::Length() const {
3578 if (IsDeadCheck("v8::Array::Length()")) return 0;
3579 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3580 i::Object* length = obj->length();
3581 if (length->IsSmi()) {
3582 return i::Smi::cast(length)->value();
3583 } else {
3584 return static_cast<uint32_t>(length->Number());
3585 }
3586}
3587
3588
3589Local<Object> Array::CloneElementAt(uint32_t index) {
3590 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3591 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3592 if (!self->HasFastElements()) {
3593 return Local<Object>();
3594 }
3595 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3596 i::Object* paragon = elms->get(index);
3597 if (!paragon->IsJSObject()) {
3598 return Local<Object>();
3599 }
3600 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3601 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003602 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003603 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3604 has_pending_exception = result.is_null();
3605 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3606 return Utils::ToLocal(result);
3607}
3608
3609
3610Local<String> v8::String::NewSymbol(const char* data, int length) {
3611 EnsureInitialized("v8::String::NewSymbol()");
3612 LOG_API("String::NewSymbol(char)");
3613 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003614 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003615 i::Handle<i::String> result =
3616 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3617 return Utils::ToLocal(result);
3618}
3619
3620
3621Local<Number> v8::Number::New(double value) {
3622 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003623 if (isnan(value)) {
3624 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3625 value = i::OS::nan_value();
3626 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003627 ENTER_V8;
3628 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3629 return Utils::NumberToLocal(result);
3630}
3631
3632
3633Local<Integer> v8::Integer::New(int32_t value) {
3634 EnsureInitialized("v8::Integer::New()");
3635 if (i::Smi::IsValid(value)) {
3636 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3637 }
3638 ENTER_V8;
3639 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3640 return Utils::IntegerToLocal(result);
3641}
3642
3643
Steve Block3ce2e202009-11-05 08:53:23 +00003644Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3645 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3646 if (fits_into_int32_t) {
3647 return Integer::New(static_cast<int32_t>(value));
3648 }
3649 ENTER_V8;
3650 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3651 return Utils::IntegerToLocal(result);
3652}
3653
3654
Steve Blocka7e24c12009-10-30 11:49:00 +00003655void V8::IgnoreOutOfMemoryException() {
3656 thread_local.set_ignore_out_of_memory(true);
3657}
3658
3659
3660bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3661 EnsureInitialized("v8::V8::AddMessageListener()");
3662 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3663 ENTER_V8;
3664 HandleScope scope;
3665 NeanderArray listeners(i::Factory::message_listeners());
3666 NeanderObject obj(2);
3667 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3668 obj.set(1, data.IsEmpty() ?
3669 i::Heap::undefined_value() :
3670 *Utils::OpenHandle(*data));
3671 listeners.add(obj.value());
3672 return true;
3673}
3674
3675
3676void V8::RemoveMessageListeners(MessageCallback that) {
3677 EnsureInitialized("v8::V8::RemoveMessageListener()");
3678 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3679 ENTER_V8;
3680 HandleScope scope;
3681 NeanderArray listeners(i::Factory::message_listeners());
3682 for (int i = 0; i < listeners.length(); i++) {
3683 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3684
3685 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3686 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3687 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3688 listeners.set(i, i::Heap::undefined_value());
3689 }
3690 }
3691}
3692
3693
3694void V8::SetCounterFunction(CounterLookupCallback callback) {
3695 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3696 i::StatsTable::SetCounterFunction(callback);
3697}
3698
3699void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3700 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3701 i::StatsTable::SetCreateHistogramFunction(callback);
3702}
3703
3704void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3705 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3706 i::StatsTable::SetAddHistogramSampleFunction(callback);
3707}
3708
3709void V8::EnableSlidingStateWindow() {
3710 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3711 i::Logger::EnableSlidingStateWindow();
3712}
3713
3714
3715void V8::SetFailedAccessCheckCallbackFunction(
3716 FailedAccessCheckCallback callback) {
3717 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3718 i::Top::SetFailedAccessCheckCallback(callback);
3719}
3720
3721
3722void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3723 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3724 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3725 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3726}
3727
3728
3729int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3730 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3731 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3732}
3733
3734
3735void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3736 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3737 i::Heap::SetGlobalGCPrologueCallback(callback);
3738}
3739
3740
3741void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3742 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3743 i::Heap::SetGlobalGCEpilogueCallback(callback);
3744}
3745
3746
Steve Block6ded16b2010-05-10 14:33:55 +01003747void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3748 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3749 i::Heap::AddGCPrologueCallback(callback, gc_type);
3750}
3751
3752
3753void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3754 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3755 i::Heap::RemoveGCPrologueCallback(callback);
3756}
3757
3758
3759void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3760 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3761 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3762}
3763
3764
3765void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3766 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3767 i::Heap::RemoveGCEpilogueCallback(callback);
3768}
3769
3770
Steve Blocka7e24c12009-10-30 11:49:00 +00003771void V8::PauseProfiler() {
3772#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003773 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003774#endif
3775}
3776
3777
3778void V8::ResumeProfiler() {
3779#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003780 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003781#endif
3782}
3783
3784
3785bool V8::IsProfilerPaused() {
3786#ifdef ENABLE_LOGGING_AND_PROFILING
3787 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3788#else
3789 return true;
3790#endif
3791}
3792
3793
Andrei Popescu402d9372010-02-26 13:31:12 +00003794void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003795#ifdef ENABLE_LOGGING_AND_PROFILING
3796 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3797 // Snapshot mode: resume modules, perform GC, then pause only
3798 // those modules which haven't been started prior to making a
3799 // snapshot.
3800
Steve Block6ded16b2010-05-10 14:33:55 +01003801 // Make a GC prior to taking a snapshot.
3802 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003803 // Reset snapshot flag and CPU module flags.
3804 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3805 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003806 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003807 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003808 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003809 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003810 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003811 }
3812#endif
3813}
3814
3815
Andrei Popescu402d9372010-02-26 13:31:12 +00003816void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003817#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003818 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003819#endif
3820}
3821
3822
3823int V8::GetActiveProfilerModules() {
3824#ifdef ENABLE_LOGGING_AND_PROFILING
3825 return i::Logger::GetActiveProfilerModules();
3826#else
3827 return PROFILER_MODULE_NONE;
3828#endif
3829}
3830
3831
3832int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3833#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003834 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003835 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3836#endif
3837 return 0;
3838}
3839
3840
3841int V8::GetCurrentThreadId() {
3842 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3843 EnsureInitialized("V8::GetCurrentThreadId()");
3844 return i::Top::thread_id();
3845}
3846
3847
3848void V8::TerminateExecution(int thread_id) {
3849 if (!i::V8::IsRunning()) return;
3850 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3851 // If the thread_id identifies the current thread just terminate
3852 // execution right away. Otherwise, ask the thread manager to
3853 // terminate the thread with the given id if any.
3854 if (thread_id == i::Top::thread_id()) {
3855 i::StackGuard::TerminateExecution();
3856 } else {
3857 i::ThreadManager::TerminateExecution(thread_id);
3858 }
3859}
3860
3861
3862void V8::TerminateExecution() {
3863 if (!i::V8::IsRunning()) return;
3864 i::StackGuard::TerminateExecution();
3865}
3866
3867
Steve Block6ded16b2010-05-10 14:33:55 +01003868bool V8::IsExecutionTerminating() {
3869 if (!i::V8::IsRunning()) return false;
3870 if (i::Top::has_scheduled_exception()) {
3871 return i::Top::scheduled_exception() == i::Heap::termination_exception();
3872 }
3873 return false;
3874}
3875
3876
Steve Blocka7e24c12009-10-30 11:49:00 +00003877String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3878 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3879 if (obj.IsEmpty()) {
3880 str_ = NULL;
3881 length_ = 0;
3882 return;
3883 }
3884 ENTER_V8;
3885 HandleScope scope;
3886 TryCatch try_catch;
3887 Handle<String> str = obj->ToString();
3888 if (str.IsEmpty()) {
3889 str_ = NULL;
3890 length_ = 0;
3891 } else {
3892 length_ = str->Utf8Length();
3893 str_ = i::NewArray<char>(length_ + 1);
3894 str->WriteUtf8(str_);
3895 }
3896}
3897
3898
3899String::Utf8Value::~Utf8Value() {
3900 i::DeleteArray(str_);
3901}
3902
3903
3904String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3905 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3906 if (obj.IsEmpty()) {
3907 str_ = NULL;
3908 length_ = 0;
3909 return;
3910 }
3911 ENTER_V8;
3912 HandleScope scope;
3913 TryCatch try_catch;
3914 Handle<String> str = obj->ToString();
3915 if (str.IsEmpty()) {
3916 str_ = NULL;
3917 length_ = 0;
3918 } else {
3919 length_ = str->Length();
3920 str_ = i::NewArray<char>(length_ + 1);
3921 str->WriteAscii(str_);
3922 }
3923}
3924
3925
3926String::AsciiValue::~AsciiValue() {
3927 i::DeleteArray(str_);
3928}
3929
3930
3931String::Value::Value(v8::Handle<v8::Value> obj) {
3932 EnsureInitialized("v8::String::Value::Value()");
3933 if (obj.IsEmpty()) {
3934 str_ = NULL;
3935 length_ = 0;
3936 return;
3937 }
3938 ENTER_V8;
3939 HandleScope scope;
3940 TryCatch try_catch;
3941 Handle<String> str = obj->ToString();
3942 if (str.IsEmpty()) {
3943 str_ = NULL;
3944 length_ = 0;
3945 } else {
3946 length_ = str->Length();
3947 str_ = i::NewArray<uint16_t>(length_ + 1);
3948 str->Write(str_);
3949 }
3950}
3951
3952
3953String::Value::~Value() {
3954 i::DeleteArray(str_);
3955}
3956
3957Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3958 LOG_API("RangeError");
3959 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
3960 ENTER_V8;
3961 i::Object* error;
3962 {
3963 HandleScope scope;
3964 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3965 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3966 error = *result;
3967 }
3968 i::Handle<i::Object> result(error);
3969 return Utils::ToLocal(result);
3970}
3971
3972Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3973 LOG_API("ReferenceError");
3974 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
3975 ENTER_V8;
3976 i::Object* error;
3977 {
3978 HandleScope scope;
3979 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3980 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3981 error = *result;
3982 }
3983 i::Handle<i::Object> result(error);
3984 return Utils::ToLocal(result);
3985}
3986
3987Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3988 LOG_API("SyntaxError");
3989 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
3990 ENTER_V8;
3991 i::Object* error;
3992 {
3993 HandleScope scope;
3994 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3995 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3996 error = *result;
3997 }
3998 i::Handle<i::Object> result(error);
3999 return Utils::ToLocal(result);
4000}
4001
4002Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4003 LOG_API("TypeError");
4004 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4005 ENTER_V8;
4006 i::Object* error;
4007 {
4008 HandleScope scope;
4009 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4010 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4011 error = *result;
4012 }
4013 i::Handle<i::Object> result(error);
4014 return Utils::ToLocal(result);
4015}
4016
4017Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4018 LOG_API("Error");
4019 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4020 ENTER_V8;
4021 i::Object* error;
4022 {
4023 HandleScope scope;
4024 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4025 i::Handle<i::Object> result = i::Factory::NewError(message);
4026 error = *result;
4027 }
4028 i::Handle<i::Object> result(error);
4029 return Utils::ToLocal(result);
4030}
4031
4032
4033// --- D e b u g S u p p o r t ---
4034
4035#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004036
4037static v8::Debug::EventCallback event_callback = NULL;
4038
4039static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4040 if (event_callback) {
4041 event_callback(event_details.GetEvent(),
4042 event_details.GetExecutionState(),
4043 event_details.GetEventData(),
4044 event_details.GetCallbackData());
4045 }
4046}
4047
4048
Steve Blocka7e24c12009-10-30 11:49:00 +00004049bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4050 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4051 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4052 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004053
4054 event_callback = that;
4055
4056 HandleScope scope;
4057 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4058 if (that != NULL) {
4059 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4060 }
4061 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4062 return true;
4063}
4064
4065
4066bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4067 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4068 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4069 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004070 HandleScope scope;
4071 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4072 if (that != NULL) {
4073 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4074 }
4075 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4076 return true;
4077}
4078
4079
4080bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4081 Handle<Value> data) {
4082 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4083 ENTER_V8;
4084 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4085 Utils::OpenHandle(*data));
4086 return true;
4087}
4088
4089
4090void Debug::DebugBreak() {
4091 if (!i::V8::IsRunning()) return;
4092 i::StackGuard::DebugBreak();
4093}
4094
4095
4096static v8::Debug::MessageHandler message_handler = NULL;
4097
4098static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4099 if (message_handler) {
4100 v8::String::Value json(message.GetJSON());
4101 message_handler(*json, json.length(), message.GetClientData());
4102 }
4103}
4104
4105
4106void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4107 bool message_handler_thread) {
4108 EnsureInitialized("v8::Debug::SetMessageHandler");
4109 ENTER_V8;
4110 // Message handler thread not supported any more. Parameter temporally left in
4111 // the API for client compatability reasons.
4112 CHECK(!message_handler_thread);
4113
4114 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4115 message_handler = handler;
4116 if (message_handler != NULL) {
4117 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4118 } else {
4119 i::Debugger::SetMessageHandler(NULL);
4120 }
4121}
4122
4123
4124void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4125 EnsureInitialized("v8::Debug::SetMessageHandler");
4126 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004127 i::Debugger::SetMessageHandler(handler);
4128}
4129
4130
4131void Debug::SendCommand(const uint16_t* command, int length,
4132 ClientData* client_data) {
4133 if (!i::V8::IsRunning()) return;
4134 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4135 client_data);
4136}
4137
4138
4139void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4140 int period) {
4141 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4142 ENTER_V8;
4143 i::Debugger::SetHostDispatchHandler(handler, period);
4144}
4145
4146
Steve Blockd0582a62009-12-15 09:54:21 +00004147void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004148 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004149 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4150 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004151 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004152}
4153
4154
Steve Blocka7e24c12009-10-30 11:49:00 +00004155Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4156 v8::Handle<v8::Value> data) {
4157 if (!i::V8::IsRunning()) return Local<Value>();
4158 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4159 ENTER_V8;
4160 i::Handle<i::Object> result;
4161 EXCEPTION_PREAMBLE();
4162 if (data.IsEmpty()) {
4163 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4164 i::Factory::undefined_value(),
4165 &has_pending_exception);
4166 } else {
4167 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4168 Utils::OpenHandle(*data),
4169 &has_pending_exception);
4170 }
4171 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4172 return Utils::ToLocal(result);
4173}
4174
4175
4176Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4177 if (!i::V8::IsRunning()) return Local<Value>();
4178 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4179 ENTER_V8;
4180 v8::HandleScope scope;
4181 i::Debug::Load();
4182 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4183 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4184 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4185 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4186 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4187 const int kArgc = 1;
4188 v8::Handle<v8::Value> argv[kArgc] = { obj };
4189 EXCEPTION_PREAMBLE();
4190 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4191 kArgc,
4192 argv);
4193 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4194 return scope.Close(result);
4195}
4196
4197
Leon Clarkee46be812010-01-19 14:06:41 +00004198bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4199 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004200}
Leon Clarkee46be812010-01-19 14:06:41 +00004201
4202void Debug::ProcessDebugMessages() {
4203 i::Execution::ProcessDebugMesssages(true);
4204}
4205
Steve Block6ded16b2010-05-10 14:33:55 +01004206Local<Context> Debug::GetDebugContext() {
4207 EnsureInitialized("v8::Debug::GetDebugContext()");
4208 ENTER_V8;
4209 return Utils::ToLocal(i::Debugger::GetDebugContext());
4210}
4211
Steve Blocka7e24c12009-10-30 11:49:00 +00004212#endif // ENABLE_DEBUGGER_SUPPORT
4213
Steve Block6ded16b2010-05-10 14:33:55 +01004214
4215#ifdef ENABLE_LOGGING_AND_PROFILING
4216
4217Handle<String> CpuProfileNode::GetFunctionName() const {
4218 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4219 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4220 const i::CodeEntry* entry = node->entry();
4221 if (!entry->has_name_prefix()) {
4222 return Handle<String>(ToApi<String>(
4223 i::Factory::LookupAsciiSymbol(entry->name())));
4224 } else {
4225 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4226 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4227 i::Factory::LookupAsciiSymbol(entry->name()))));
4228 }
4229}
4230
4231
4232Handle<String> CpuProfileNode::GetScriptResourceName() const {
4233 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4234 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4235 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4236 node->entry()->resource_name())));
4237}
4238
4239
4240int CpuProfileNode::GetLineNumber() const {
4241 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4242 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4243}
4244
4245
4246double CpuProfileNode::GetTotalTime() const {
4247 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4248 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4249}
4250
4251
4252double CpuProfileNode::GetSelfTime() const {
4253 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4254 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4255}
4256
4257
4258double CpuProfileNode::GetTotalSamplesCount() const {
4259 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4260 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4261}
4262
4263
4264double CpuProfileNode::GetSelfSamplesCount() const {
4265 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4266 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4267}
4268
4269
4270unsigned CpuProfileNode::GetCallUid() const {
4271 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4272 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4273}
4274
4275
4276int CpuProfileNode::GetChildrenCount() const {
4277 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4278 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4279}
4280
4281
4282const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4283 IsDeadCheck("v8::CpuProfileNode::GetChild");
4284 const i::ProfileNode* child =
4285 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4286 return reinterpret_cast<const CpuProfileNode*>(child);
4287}
4288
4289
4290unsigned CpuProfile::GetUid() const {
4291 IsDeadCheck("v8::CpuProfile::GetUid");
4292 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4293}
4294
4295
4296Handle<String> CpuProfile::GetTitle() const {
4297 IsDeadCheck("v8::CpuProfile::GetTitle");
4298 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4299 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4300 profile->title())));
4301}
4302
4303
4304const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4305 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4306 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4307 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4308}
4309
4310
4311const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4312 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4313 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4314 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4315}
4316
4317
4318int CpuProfiler::GetProfilesCount() {
4319 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4320 return i::CpuProfiler::GetProfilesCount();
4321}
4322
4323
Leon Clarkef7060e22010-06-03 12:02:55 +01004324const CpuProfile* CpuProfiler::GetProfile(int index,
4325 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004326 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004327 return reinterpret_cast<const CpuProfile*>(
4328 i::CpuProfiler::GetProfile(
4329 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4330 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004331}
4332
4333
Leon Clarkef7060e22010-06-03 12:02:55 +01004334const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4335 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004336 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004337 return reinterpret_cast<const CpuProfile*>(
4338 i::CpuProfiler::FindProfile(
4339 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4340 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004341}
4342
4343
4344void CpuProfiler::StartProfiling(Handle<String> title) {
4345 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4346 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4347}
4348
4349
Leon Clarkef7060e22010-06-03 12:02:55 +01004350const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4351 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004352 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4353 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004354 i::CpuProfiler::StopProfiling(
4355 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4356 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004357}
4358
4359#endif // ENABLE_LOGGING_AND_PROFILING
4360
4361
Steve Blocka7e24c12009-10-30 11:49:00 +00004362namespace internal {
4363
4364
4365HandleScopeImplementer* HandleScopeImplementer::instance() {
4366 return &thread_local;
4367}
4368
4369
4370void HandleScopeImplementer::FreeThreadResources() {
4371 thread_local.Free();
4372}
4373
4374
4375char* HandleScopeImplementer::ArchiveThread(char* storage) {
4376 return thread_local.ArchiveThreadHelper(storage);
4377}
4378
4379
4380char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4381 v8::ImplementationUtilities::HandleScopeData* current =
4382 v8::ImplementationUtilities::CurrentHandleScope();
4383 handle_scope_data_ = *current;
4384 memcpy(storage, this, sizeof(*this));
4385
4386 ResetAfterArchive();
4387 current->Initialize();
4388
4389 return storage + ArchiveSpacePerThread();
4390}
4391
4392
4393int HandleScopeImplementer::ArchiveSpacePerThread() {
4394 return sizeof(thread_local);
4395}
4396
4397
4398char* HandleScopeImplementer::RestoreThread(char* storage) {
4399 return thread_local.RestoreThreadHelper(storage);
4400}
4401
4402
4403char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4404 memcpy(this, storage, sizeof(*this));
4405 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4406 return storage + ArchiveSpacePerThread();
4407}
4408
4409
4410void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4411 // Iterate over all handles in the blocks except for the last.
4412 for (int i = blocks()->length() - 2; i >= 0; --i) {
4413 Object** block = blocks()->at(i);
4414 v->VisitPointers(block, &block[kHandleBlockSize]);
4415 }
4416
4417 // Iterate over live handles in the last block (if any).
4418 if (!blocks()->is_empty()) {
4419 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4420 }
4421
4422 if (!saved_contexts_.is_empty()) {
4423 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4424 v->VisitPointers(start, start + saved_contexts_.length());
4425 }
4426}
4427
4428
4429void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4430 v8::ImplementationUtilities::HandleScopeData* current =
4431 v8::ImplementationUtilities::CurrentHandleScope();
4432 thread_local.handle_scope_data_ = *current;
4433 thread_local.IterateThis(v);
4434}
4435
4436
4437char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4438 HandleScopeImplementer* thread_local =
4439 reinterpret_cast<HandleScopeImplementer*>(storage);
4440 thread_local->IterateThis(v);
4441 return storage + ArchiveSpacePerThread();
4442}
4443
4444} } // namespace v8::internal