blob: 885c68353f83a224c4fe2b1565f829682bfd7379 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2007-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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 "bootstrapper.h"
32#include "compiler.h"
33#include "debug.h"
34#include "execution.h"
35#include "global-handles.h"
36#include "platform.h"
37#include "serialize.h"
38#include "snapshot.h"
39
40
41namespace i = v8::internal;
42#define LOG_API(expr) LOG(ApiEntryCall(expr))
43
44
45namespace v8 {
46
47
48#define ON_BAILOUT(location, code) \
49 if (IsDeadCheck(location)) { \
50 code; \
51 UNREACHABLE(); \
52 }
53
54
55#define EXCEPTION_PREAMBLE() \
56 thread_local.IncrementCallDepth(); \
57 ASSERT(!i::Top::external_caught_exception()); \
58 bool has_pending_exception = false
59
60
61#define EXCEPTION_BAILOUT_CHECK(value) \
62 do { \
63 thread_local.DecrementCallDepth(); \
64 if (has_pending_exception) { \
65 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
66 if (!thread_local.IgnoreOutOfMemory()) \
67 i::V8::FatalProcessOutOfMemory(NULL); \
68 } \
69 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
70 i::Top::optional_reschedule_exception(call_depth_is_zero); \
71 return value; \
72 } \
73 } while (false)
74
75
76// --- 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 ---
77
78
79static i::HandleScopeImplementer thread_local;
80
81
82// --- E x c e p t i o n B e h a v i o r ---
83
84
85static bool has_shut_down = false;
86static FatalErrorCallback exception_behavior = NULL;
87
88
89static void DefaultFatalErrorHandler(const char* location,
90 const char* message) {
91 API_Fatal(location, message);
92}
93
94
95
96static FatalErrorCallback& GetFatalErrorHandler() {
97 if (exception_behavior == NULL) {
98 exception_behavior = DefaultFatalErrorHandler;
99 }
100 return exception_behavior;
101}
102
103
104
105// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
106// The default fatal error handler is called and execution is stopped.
107void i::V8::FatalProcessOutOfMemory(const char* location) {
108 has_shut_down = true;
109 FatalErrorCallback callback = GetFatalErrorHandler();
110 callback(location, "Allocation failed - process out of memory");
111 // If the callback returns, we stop execution.
112 UNREACHABLE();
113}
114
115
116void V8::SetFatalErrorHandler(FatalErrorCallback that) {
117 exception_behavior = that;
118}
119
120
121bool Utils::ReportApiFailure(const char* location, const char* message) {
122 FatalErrorCallback callback = GetFatalErrorHandler();
123 callback(location, message);
124 has_shut_down = true;
125 return false;
126}
127
128
129bool V8::IsDead() {
130 return has_shut_down;
131}
132
133
134static inline bool ApiCheck(bool condition,
135 const char* location,
136 const char* message) {
137 return condition ? true : Utils::ReportApiFailure(location, message);
138}
139
140
141static bool ReportV8Dead(const char* location) {
142 FatalErrorCallback callback = GetFatalErrorHandler();
143 callback(location, "V8 is no longer useable");
144 return true;
145}
146
147
148static bool ReportEmptyHandle(const char* location) {
149 FatalErrorCallback callback = GetFatalErrorHandler();
150 callback(location, "Reading from empty handle");
151 return true;
152}
153
154
155/**
156 * IsDeadCheck checks that the vm is useable. If, for instance, the vm has been
157 * out of memory at some point this check will fail. It should be called on
158 * entry to all methods that touch anything in the heap, except destructors
159 * which you sometimes can't avoid calling after the vm has crashed. Functions
160 * that call EnsureInitialized or ON_BAILOUT don't have to also call
161 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
162 * can arrange to return if the VM is dead. This is needed to ensure that no VM
163 * heap allocations are attempted on a dead VM. EnsureInitialized has the
164 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
165 * yet been done.
166 */
167static inline bool IsDeadCheck(const char* location) {
168 return has_shut_down ? ReportV8Dead(location) : false;
169}
170
171
172static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
173 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
174}
175
176
177static inline bool EmptyCheck(const char* location, v8::Data* obj) {
178 return (obj == 0) ? ReportEmptyHandle(location) : false;
179}
180
181// --- S t a t i c s ---
182
183
184static i::StringInputBuffer write_input_buffer;
185
186
187static void EnsureInitialized(const char* location) {
188 if (IsDeadCheck(location)) return;
189 ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
190}
191
192
193v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
194 if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>();
195 EnsureInitialized("v8::Undefined()");
196 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
197}
198
199
200v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
201 if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>();
202 EnsureInitialized("v8::Null()");
203 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
204}
205
206
207v8::Handle<v8::Boolean> ImplementationUtilities::True() {
208 if (IsDeadCheck("v8::True()")) return v8::Handle<v8::Boolean>();
209 EnsureInitialized("v8::True()");
210 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
211}
212
213
214v8::Handle<v8::Boolean> ImplementationUtilities::False() {
215 if (IsDeadCheck("v8::False()")) return v8::Handle<v8::Boolean>();
216 EnsureInitialized("v8::False()");
217 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
218}
219
220
221void V8::SetFlagsFromString(const char* str, int length) {
222 i::FlagList::SetFlagsFromString(str, length);
223}
224
225
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000226void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
227 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
228}
229
230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
232 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000233 // If we're passed an empty handle, we throw an undefined exception
234 // to deal more gracefully with out of memory situations.
235 if (value.IsEmpty()) {
236 i::Top::ScheduleThrow(i::Heap::undefined_value());
237 } else {
238 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
239 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 return v8::Undefined();
241}
242
243
244RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
245
246
247RegisteredExtension::RegisteredExtension(Extension* extension)
248 : extension_(extension), state_(UNVISITED) { }
249
250
251void RegisteredExtension::Register(RegisteredExtension* that) {
252 that->next_ = RegisteredExtension::first_extension_;
253 RegisteredExtension::first_extension_ = that;
254}
255
256
257void RegisterExtension(Extension* that) {
258 RegisteredExtension* extension = new RegisteredExtension(that);
259 RegisteredExtension::Register(extension);
260}
261
262
263Extension::Extension(const char* name,
264 const char* source,
265 int dep_count,
266 const char** deps)
267 : name_(name),
268 source_(source),
269 dep_count_(dep_count),
270 deps_(deps),
271 auto_enable_(false) { }
272
273
274v8::Handle<Primitive> Undefined() {
275 LOG_API("Undefined");
276 return ImplementationUtilities::Undefined();
277}
278
279
280v8::Handle<Primitive> Null() {
281 LOG_API("Null");
282 return ImplementationUtilities::Null();
283}
284
285
286v8::Handle<Boolean> True() {
287 LOG_API("True");
288 return ImplementationUtilities::True();
289}
290
291
292v8::Handle<Boolean> False() {
293 LOG_API("False");
294 return ImplementationUtilities::False();
295}
296
297
298ResourceConstraints::ResourceConstraints()
299 : max_young_space_size_(0),
300 max_old_space_size_(0),
301 stack_limit_(NULL) { }
302
303
304bool SetResourceConstraints(ResourceConstraints* constraints) {
305 bool result = i::Heap::ConfigureHeap(constraints->max_young_space_size(),
306 constraints->max_old_space_size());
307 if (!result) return false;
308 if (constraints->stack_limit() != NULL) {
309 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
310 i::StackGuard::SetStackLimit(limit);
311 }
312 return true;
313}
314
315
316void** V8::GlobalizeReference(void** obj) {
317 LOG_API("Persistent::New");
318 if (IsDeadCheck("V8::Persistent::New")) return NULL;
319 i::Handle<i::Object> result =
320 i::GlobalHandles::Create(*reinterpret_cast<i::Object**>(obj));
321 return reinterpret_cast<void**>(result.location());
322}
323
324
325void V8::MakeWeak(void** object, void* parameters,
326 WeakReferenceCallback callback) {
327 LOG_API("MakeWeak");
328 i::GlobalHandles::MakeWeak(reinterpret_cast<i::Object**>(object), parameters,
329 callback);
330}
331
332
333void V8::ClearWeak(void** obj) {
334 LOG_API("ClearWeak");
335 i::GlobalHandles::ClearWeakness(reinterpret_cast<i::Object**>(obj));
336}
337
338
339bool V8::IsGlobalNearDeath(void** obj) {
340 LOG_API("IsGlobalNearDeath");
341 if (has_shut_down) return false;
342 return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));
343}
344
345
346bool V8::IsGlobalWeak(void** obj) {
347 LOG_API("IsGlobalWeak");
348 if (has_shut_down) return false;
349 return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));
350}
351
352
353void V8::DisposeGlobal(void** obj) {
354 LOG_API("DisposeGlobal");
355 if (has_shut_down) return;
356 i::GlobalHandles::Destroy(reinterpret_cast<i::Object**>(obj));
357}
358
359// --- H a n d l e s ---
360
361
362HandleScope::Data HandleScope::current_ = { -1, NULL, NULL };
363
364
365int HandleScope::NumberOfHandles() {
366 int n = thread_local.Blocks()->length();
367 if (n == 0) return 0;
368 return ((n - 1) * i::kHandleBlockSize) +
369 (current_.next - thread_local.Blocks()->last());
370}
371
372
373void** v8::HandleScope::CreateHandle(void* value) {
374 void** result = current_.next;
375 if (result == current_.limit) {
376 // Make sure there's at least one scope on the stack and that the
377 // top of the scope stack isn't a barrier.
378 if (!ApiCheck(current_.extensions >= 0,
379 "v8::HandleScope::CreateHandle()",
380 "Cannot create a handle without a HandleScope")) {
381 return NULL;
382 }
383 // If there's more room in the last block, we use that. This is used
384 // for fast creation of scopes after scope barriers.
385 if (!thread_local.Blocks()->is_empty()) {
386 void** limit = &thread_local.Blocks()->last()[i::kHandleBlockSize];
387 if (current_.limit != limit) {
388 current_.limit = limit;
389 }
390 }
391
392 // If we still haven't found a slot for the handle, we extend the
393 // current handle scope by allocating a new handle block.
394 if (result == current_.limit) {
395 // If there's a spare block, use it for growing the current scope.
396 result = thread_local.GetSpareOrNewBlock();
397 // Add the extension to the global list of blocks, but count the
398 // extension as part of the current scope.
399 thread_local.Blocks()->Add(result);
400 current_.extensions++;
401 current_.limit = &result[i::kHandleBlockSize];
402 }
403 }
404
405 // Update the current next field, set the value in the created
406 // handle, and return the result.
407 ASSERT(result < current_.limit);
408 current_.next = result + 1;
409 *result = value;
410 return result;
411}
412
413
414void Context::Enter() {
415 if (IsDeadCheck("v8::Context::Enter()")) return;
416 i::Handle<i::Context> env = Utils::OpenHandle(this);
kasper.lund44510672008-07-25 07:37:58 +0000417 thread_local.EnterContext(env);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418
kasper.lund44510672008-07-25 07:37:58 +0000419 thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420 i::Top::set_context(*env);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421}
422
423
424void Context::Exit() {
425 if (has_shut_down) return;
kasper.lund44510672008-07-25 07:37:58 +0000426 if (!ApiCheck(thread_local.LeaveLastContext(),
427 "v8::Context::Exit()",
428 "Cannot exit non-entered context")) {
429 return;
430 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000432 // Content of 'last_context' could be NULL.
kasper.lund44510672008-07-25 07:37:58 +0000433 i::Handle<i::Object> last_context = thread_local.RestoreContext();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000434 i::Top::set_context(static_cast<i::Context*>(*last_context));
435 i::GlobalHandles::Destroy(last_context.location());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000436}
437
438
439void v8::HandleScope::DeleteExtensions() {
440 ASSERT(current_.extensions != 0);
441 thread_local.DeleteExtensions(current_.extensions);
442}
443
444
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445void HandleScope::ZapRange(void** start, void** end) {
446 if (start == NULL) return;
447 for (void** p = start; p < end; p++) {
448 *p = reinterpret_cast<void*>(v8::internal::kHandleZapValue);
449 }
450}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451
452
453void** v8::HandleScope::RawClose(void** value) {
454 if (!ApiCheck(!is_closed_,
455 "v8::HandleScope::Close()",
456 "Local scope has already been closed")) {
457 return 0;
458 }
459 LOG_API("CloseHandleScope");
460
461 // Read the result before popping the handle block.
462 i::Object* result = reinterpret_cast<i::Object*>(*value);
463 is_closed_ = true;
464 RestorePreviousState();
465
466 // Allocate a new handle on the previous handle block.
467 i::Handle<i::Object> handle(result);
468 return reinterpret_cast<void**>(handle.location());
469}
470
471
472// --- N e a n d e r ---
473
474
475// A constructor cannot easily return an error value, therefore it is necessary
476// to check for a dead VM with ON_BAILOUT before constructing any Neander
477// objects. To remind you about this there is no HandleScope in the
478// NeanderObject constructor. When you add one to the site calling the
479// constructor you should check that you ensured the VM was not dead first.
480NeanderObject::NeanderObject(int size) {
481 EnsureInitialized("v8::Nowhere");
482 value_ = i::Factory::NewNeanderObject();
483 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
484 value_->set_elements(*elements);
485}
486
487
488int NeanderObject::size() {
489 return i::FixedArray::cast(value_->elements())->length();
490}
491
492
493NeanderArray::NeanderArray() : obj_(2) {
494 obj_.set(0, i::Smi::FromInt(0));
495}
496
497
498int NeanderArray::length() {
499 return i::Smi::cast(obj_.get(0))->value();
500}
501
502
503i::Object* NeanderArray::get(int offset) {
504 ASSERT(0 <= offset);
505 ASSERT(offset < length());
506 return obj_.get(offset + 1);
507}
508
509
510// This method cannot easily return an error value, therefore it is necessary
511// to check for a dead VM with ON_BAILOUT before calling it. To remind you
512// about this there is no HandleScope in this method. When you add one to the
513// site calling this method you should check that you ensured the VM was not
514// dead first.
515void NeanderArray::add(i::Handle<i::Object> value) {
516 int length = this->length();
517 int size = obj_.size();
518 if (length == size - 1) {
519 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
520 for (int i = 0; i < length; i++)
521 new_elms->set(i + 1, get(i));
522 obj_.value()->set_elements(*new_elms);
523 }
524 obj_.set(length + 1, *value);
525 obj_.set(0, i::Smi::FromInt(length + 1));
526}
527
528
529void NeanderArray::set(int index, i::Object* value) {
530 if (index < 0 || index >= this->length()) return;
531 obj_.set(index + 1, value);
532}
533
534
535// --- T e m p l a t e ---
536
537
538static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
539 that->set_tag(i::Smi::FromInt(type));
540}
541
542
543void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
544 v8::PropertyAttribute attribute) {
545 if (IsDeadCheck("v8::Template::SetProperty()")) return;
546 HandleScope scope;
547 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
548 if (list->IsUndefined()) {
549 list = NeanderArray().value();
550 Utils::OpenHandle(this)->set_property_list(*list);
551 }
552 NeanderArray array(list);
553 array.add(Utils::OpenHandle(*name));
554 array.add(Utils::OpenHandle(*value));
555 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
556}
557
558
559// --- F u n c t i o n T e m p l a t e ---
560static void InitializeFunctionTemplate(
561 i::Handle<i::FunctionTemplateInfo> info) {
562 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
563 info->set_flag(0);
564}
565
566
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
568 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
569 return Local<ObjectTemplate>();
570 }
571 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
572 if (result->IsUndefined()) {
573 result = Utils::OpenHandle(*ObjectTemplate::New());
574 Utils::OpenHandle(this)->set_prototype_template(*result);
575 }
576 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
577}
578
579
580void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
581 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
582 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
583}
584
585
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586// To distinguish the function templates, so that we can find them in the
587// function cache of the global context.
588static int next_serial_number = 0;
589
590
591Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
592 v8::Handle<Value> data, v8::Handle<Signature> signature) {
593 EnsureInitialized("v8::FunctionTemplate::New()");
594 LOG_API("FunctionTemplate::New");
595 i::Handle<i::Struct> struct_obj =
596 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
597 i::Handle<i::FunctionTemplateInfo> obj =
598 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
599 InitializeFunctionTemplate(obj);
600 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000601 if (callback != 0) {
602 if (data.IsEmpty()) data = v8::Undefined();
603 Utils::ToLocal(obj)->SetCallHandler(callback, data);
604 }
605 obj->set_undetectable(false);
606 obj->set_needs_access_check(false);
607
608 if (!signature.IsEmpty())
609 obj->set_signature(*Utils::OpenHandle(*signature));
610 return Utils::ToLocal(obj);
611}
612
613
614Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
615 int argc, Handle<FunctionTemplate> argv[]) {
616 EnsureInitialized("v8::Signature::New()");
617 LOG_API("Signature::New");
618 i::Handle<i::Struct> struct_obj =
619 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
620 i::Handle<i::SignatureInfo> obj =
621 i::Handle<i::SignatureInfo>::cast(struct_obj);
622 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
623 if (argc > 0) {
624 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
625 for (int i = 0; i < argc; i++) {
626 if (!argv[i].IsEmpty())
627 args->set(i, *Utils::OpenHandle(*argv[i]));
628 }
629 obj->set_args(*args);
630 }
631 return Utils::ToLocal(obj);
632}
633
634
635Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
636 Handle<FunctionTemplate> types[1] = { type };
637 return TypeSwitch::New(1, types);
638}
639
640
641Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
642 EnsureInitialized("v8::TypeSwitch::New()");
643 LOG_API("TypeSwitch::New");
644 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
645 for (int i = 0; i < argc; i++)
646 vector->set(i, *Utils::OpenHandle(*types[i]));
647 i::Handle<i::Struct> struct_obj =
648 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
649 i::Handle<i::TypeSwitchInfo> obj =
650 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
651 obj->set_types(*vector);
652 return Utils::ToLocal(obj);
653}
654
655
656int TypeSwitch::match(v8::Handle<Value> value) {
657 LOG_API("TypeSwitch::match");
658 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
659 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
660 i::FixedArray* types = i::FixedArray::cast(info->types());
661 for (int i = 0; i < types->length(); i++) {
662 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
663 return i + 1;
664 }
665 return 0;
666}
667
668
669void FunctionTemplate::SetCallHandler(InvocationCallback callback,
670 v8::Handle<Value> data) {
671 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
672 HandleScope scope;
673 i::Handle<i::Struct> struct_obj =
674 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
675 i::Handle<i::CallHandlerInfo> obj =
676 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
677 obj->set_callback(*FromCData(callback));
678 if (data.IsEmpty()) data = v8::Undefined();
679 obj->set_data(*Utils::OpenHandle(*data));
680 Utils::OpenHandle(this)->set_call_code(*obj);
681}
682
683
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684void FunctionTemplate::AddInstancePropertyAccessor(
685 v8::Handle<String> name,
686 AccessorGetter getter,
687 AccessorSetter setter,
688 v8::Handle<Value> data,
689 v8::AccessControl settings,
690 v8::PropertyAttribute attributes) {
691 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
692 return;
693 }
694 HandleScope scope;
695 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
696 ASSERT(getter != NULL);
697 obj->set_getter(*FromCData(getter));
698 obj->set_setter(*FromCData(setter));
699 if (data.IsEmpty()) data = v8::Undefined();
700 obj->set_data(*Utils::OpenHandle(*data));
701 obj->set_name(*Utils::OpenHandle(*name));
702 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
703 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
ager@chromium.org870a0b62008-11-04 11:43:05 +0000704 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
706
707 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
708 if (list->IsUndefined()) {
709 list = NeanderArray().value();
710 Utils::OpenHandle(this)->set_property_accessors(*list);
711 }
712 NeanderArray array(list);
713 array.add(obj);
714}
715
716
717Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
718 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
719 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
720 return Local<ObjectTemplate>();
721 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
722 Local<ObjectTemplate> templ =
723 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
724 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
725 }
726 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
727 Utils::OpenHandle(this)->instance_template()));
728 return Utils::ToLocal(result);
729}
730
731
kasper.lund212ac232008-07-16 07:07:30 +0000732void FunctionTemplate::SetClassName(Handle<String> name) {
733 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
734 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
735}
736
737
738void FunctionTemplate::SetHiddenPrototype(bool value) {
739 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
740 Utils::OpenHandle(this)->set_hidden_prototype(value);
741}
742
743
744void FunctionTemplate::SetNamedInstancePropertyHandler(
745 NamedPropertyGetter getter,
746 NamedPropertySetter setter,
747 NamedPropertyQuery query,
748 NamedPropertyDeleter remover,
749 NamedPropertyEnumerator enumerator,
750 Handle<Value> data) {
751 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
752 return;
753 }
754 HandleScope scope;
755 i::Handle<i::Struct> struct_obj =
756 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
757 i::Handle<i::InterceptorInfo> obj =
758 i::Handle<i::InterceptorInfo>::cast(struct_obj);
759 if (getter != 0) obj->set_getter(*FromCData(getter));
760 if (setter != 0) obj->set_setter(*FromCData(setter));
761 if (query != 0) obj->set_query(*FromCData(query));
762 if (remover != 0) obj->set_deleter(*FromCData(remover));
763 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
764 if (data.IsEmpty()) data = v8::Undefined();
765 obj->set_data(*Utils::OpenHandle(*data));
766 Utils::OpenHandle(this)->set_named_property_handler(*obj);
767}
768
769
770void FunctionTemplate::SetIndexedInstancePropertyHandler(
771 IndexedPropertyGetter getter,
772 IndexedPropertySetter setter,
773 IndexedPropertyQuery query,
774 IndexedPropertyDeleter remover,
775 IndexedPropertyEnumerator enumerator,
776 Handle<Value> data) {
777 if (IsDeadCheck(
778 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
779 return;
780 }
781 HandleScope scope;
782 i::Handle<i::Struct> struct_obj =
783 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
784 i::Handle<i::InterceptorInfo> obj =
785 i::Handle<i::InterceptorInfo>::cast(struct_obj);
786 if (getter != 0) obj->set_getter(*FromCData(getter));
787 if (setter != 0) obj->set_setter(*FromCData(setter));
788 if (query != 0) obj->set_query(*FromCData(query));
789 if (remover != 0) obj->set_deleter(*FromCData(remover));
790 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
791 if (data.IsEmpty()) data = v8::Undefined();
792 obj->set_data(*Utils::OpenHandle(*data));
793 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
794}
795
796
797void FunctionTemplate::SetInstanceCallAsFunctionHandler(
798 InvocationCallback callback,
799 Handle<Value> data) {
800 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
801 return;
802 }
803 HandleScope scope;
804 i::Handle<i::Struct> struct_obj =
805 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
806 i::Handle<i::CallHandlerInfo> obj =
807 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
808 obj->set_callback(*FromCData(callback));
809 if (data.IsEmpty()) data = v8::Undefined();
810 obj->set_data(*Utils::OpenHandle(*data));
811 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
812}
813
814
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815// --- O b j e c t T e m p l a t e ---
816
817
818Local<ObjectTemplate> ObjectTemplate::New() {
819 return New(Local<FunctionTemplate>());
820}
821
822
823Local<ObjectTemplate> ObjectTemplate::New(
824 v8::Handle<FunctionTemplate> constructor) {
825 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
826 EnsureInitialized("v8::ObjectTemplate::New()");
827 LOG_API("ObjectTemplate::New");
828 i::Handle<i::Struct> struct_obj =
829 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
830 i::Handle<i::ObjectTemplateInfo> obj =
831 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
832 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
833 if (!constructor.IsEmpty())
834 obj->set_constructor(*Utils::OpenHandle(*constructor));
kasper.lund212ac232008-07-16 07:07:30 +0000835 obj->set_internal_field_count(i::Smi::FromInt(0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836 return Utils::ToLocal(obj);
837}
838
839
840// Ensure that the object template has a constructor. If no
841// constructor is available we create one.
842static void EnsureConstructor(ObjectTemplate* object_template) {
843 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
844 Local<FunctionTemplate> templ = FunctionTemplate::New();
845 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
846 constructor->set_instance_template(*Utils::OpenHandle(object_template));
847 Utils::OpenHandle(object_template)->set_constructor(*constructor);
848 }
849}
850
851
852void ObjectTemplate::SetAccessor(v8::Handle<String> name,
853 AccessorGetter getter,
854 AccessorSetter setter,
855 v8::Handle<Value> data,
856 AccessControl settings,
857 PropertyAttribute attribute) {
858 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
859 HandleScope scope;
860 EnsureConstructor(this);
861 i::FunctionTemplateInfo* constructor =
862 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
863 i::Handle<i::FunctionTemplateInfo> cons(constructor);
864 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
865 getter,
866 setter,
867 data,
868 settings,
869 attribute);
870}
871
872
873void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
874 NamedPropertySetter setter,
875 NamedPropertyQuery query,
876 NamedPropertyDeleter remover,
877 NamedPropertyEnumerator enumerator,
878 Handle<Value> data) {
879 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
880 HandleScope scope;
881 EnsureConstructor(this);
882 i::FunctionTemplateInfo* constructor =
883 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
884 i::Handle<i::FunctionTemplateInfo> cons(constructor);
885 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
886 setter,
887 query,
888 remover,
889 enumerator,
890 data);
891}
892
893
894void ObjectTemplate::MarkAsUndetectable() {
895 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
896 HandleScope scope;
897 EnsureConstructor(this);
898 i::FunctionTemplateInfo* constructor =
899 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
900 i::Handle<i::FunctionTemplateInfo> cons(constructor);
901 cons->set_undetectable(true);
902}
903
904
905void ObjectTemplate::SetAccessCheckCallbacks(
906 NamedSecurityCallback named_callback,
907 IndexedSecurityCallback indexed_callback,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000908 Handle<Value> data,
909 bool turned_on_by_default) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
911 HandleScope scope;
912 EnsureConstructor(this);
913
914 i::Handle<i::Struct> struct_info =
915 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
916 i::Handle<i::AccessCheckInfo> info =
917 i::Handle<i::AccessCheckInfo>::cast(struct_info);
918 info->set_named_callback(*FromCData(named_callback));
919 info->set_indexed_callback(*FromCData(indexed_callback));
920 if (data.IsEmpty()) data = v8::Undefined();
921 info->set_data(*Utils::OpenHandle(*data));
922
923 i::FunctionTemplateInfo* constructor =
924 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
925 i::Handle<i::FunctionTemplateInfo> cons(constructor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000926 cons->set_access_check_info(*info);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000927 cons->set_needs_access_check(turned_on_by_default);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000928}
929
930
931void ObjectTemplate::SetIndexedPropertyHandler(
932 IndexedPropertyGetter getter,
933 IndexedPropertySetter setter,
934 IndexedPropertyQuery query,
935 IndexedPropertyDeleter remover,
936 IndexedPropertyEnumerator enumerator,
937 Handle<Value> data) {
938 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
939 HandleScope scope;
940 EnsureConstructor(this);
941 i::FunctionTemplateInfo* constructor =
942 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
943 i::Handle<i::FunctionTemplateInfo> cons(constructor);
944 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
945 setter,
946 query,
947 remover,
948 enumerator,
949 data);
950}
951
952
953void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
954 Handle<Value> data) {
955 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
956 HandleScope scope;
957 EnsureConstructor(this);
958 i::FunctionTemplateInfo* constructor =
959 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
960 i::Handle<i::FunctionTemplateInfo> cons(constructor);
961 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
962}
963
964
kasper.lund212ac232008-07-16 07:07:30 +0000965int ObjectTemplate::InternalFieldCount() {
966 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
967 return 0;
968 }
969 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000970}
971
972
kasper.lund212ac232008-07-16 07:07:30 +0000973void ObjectTemplate::SetInternalFieldCount(int value) {
974 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
975 if (!ApiCheck(i::Smi::IsValid(value),
976 "v8::ObjectTemplate::SetInternalFieldCount()",
977 "Invalid internal field count")) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000978 return;
979 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000980 if (value > 0) {
981 // The internal field count is set by the constructor function's
982 // construct code, so we ensure that there is a constructor
983 // function to do the setting.
984 EnsureConstructor(this);
985 }
kasper.lund212ac232008-07-16 07:07:30 +0000986 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000987}
988
989
kasper.lund212ac232008-07-16 07:07:30 +0000990// --- S c r i p t D a t a ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991
992
993ScriptData* ScriptData::PreCompile(const char* input, int length) {
994 unibrow::Utf8InputBuffer<> buf(input, length);
995 return i::PreParse(&buf, NULL);
996}
997
998
999ScriptData* ScriptData::New(unsigned* data, int length) {
1000 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1001}
1002
1003
1004// --- S c r i p t ---
1005
1006
1007Local<Script> Script::Compile(v8::Handle<String> source,
1008 v8::ScriptOrigin* origin,
1009 v8::ScriptData* script_data) {
1010 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1011 LOG_API("Script::Compile");
1012 i::Handle<i::String> str = Utils::OpenHandle(*source);
mads.s.agercbaa0602008-08-14 13:41:48 +00001013 i::Handle<i::Object> name_obj;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001014 int line_offset = 0;
1015 int column_offset = 0;
1016 if (origin != NULL) {
1017 if (!origin->ResourceName().IsEmpty()) {
1018 name_obj = Utils::OpenHandle(*origin->ResourceName());
1019 }
1020 if (!origin->ResourceLineOffset().IsEmpty()) {
1021 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1022 }
1023 if (!origin->ResourceColumnOffset().IsEmpty()) {
1024 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1025 }
1026 }
1027 EXCEPTION_PREAMBLE();
1028 i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data);
1029 // We assert that the pre-data is sane, even though we can actually
1030 // handle it if it turns out not to be in release mode.
1031 ASSERT(pre_data == NULL || pre_data->SanityCheck());
1032 // If the pre-data isn't sane we simply ignore it
1033 if (pre_data != NULL && !pre_data->SanityCheck())
1034 pre_data = NULL;
1035 i::Handle<i::JSFunction> boilerplate = i::Compiler::Compile(str,
1036 name_obj,
1037 line_offset,
1038 column_offset,
1039 NULL,
1040 pre_data);
1041 has_pending_exception = boilerplate.is_null();
1042 EXCEPTION_BAILOUT_CHECK(Local<Script>());
1043 i::Handle<i::JSFunction> result =
1044 i::Factory::NewFunctionFromBoilerplate(boilerplate,
1045 i::Top::global_context());
1046 return Local<Script>(ToApi<Script>(result));
1047}
1048
1049
mads.s.agercbaa0602008-08-14 13:41:48 +00001050Local<Script> Script::Compile(v8::Handle<String> source,
1051 v8::Handle<Value> file_name) {
1052 ScriptOrigin origin(file_name);
1053 return Compile(source, &origin);
1054}
1055
1056
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001057Local<Value> Script::Run() {
1058 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1059 LOG_API("Script::Run");
1060 i::Object* raw_result = NULL;
1061 {
1062 HandleScope scope;
1063 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1064 EXCEPTION_PREAMBLE();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001065 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001066 i::Handle<i::Object> result =
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001067 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001068 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1069 raw_result = *result;
1070 }
1071 i::Handle<i::Object> result(raw_result);
1072 return Utils::ToLocal(result);
1073}
1074
1075
1076// --- E x c e p t i o n s ---
1077
1078
1079v8::TryCatch::TryCatch()
1080 : next_(i::Top::try_catch_handler()),
1081 exception_(i::Heap::the_hole_value()),
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001082 message_(i::Smi::FromInt(0)),
1083 is_verbose_(false),
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001084 capture_message_(true),
1085 js_handler_(NULL) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086 i::Top::RegisterTryCatchHandler(this);
1087}
1088
1089
1090v8::TryCatch::~TryCatch() {
1091 i::Top::UnregisterTryCatchHandler(this);
1092}
1093
1094
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001095bool v8::TryCatch::HasCaught() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001096 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1097}
1098
1099
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001100v8::Local<Value> v8::TryCatch::Exception() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101 if (HasCaught()) {
1102 // Check for out of memory exception.
1103 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1104 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1105 } else {
1106 return v8::Local<Value>();
1107 }
1108}
1109
1110
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001111v8::Local<v8::Message> v8::TryCatch::Message() const {
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001112 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1113 i::Object* message = reinterpret_cast<i::Object*>(message_);
1114 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1115 } else {
1116 return v8::Local<v8::Message>();
1117 }
1118}
1119
1120
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121void v8::TryCatch::Reset() {
1122 exception_ = i::Heap::the_hole_value();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001123 message_ = i::Smi::FromInt(0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001124}
1125
1126
1127void v8::TryCatch::SetVerbose(bool value) {
1128 is_verbose_ = value;
1129}
1130
1131
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001132void v8::TryCatch::SetCaptureMessage(bool value) {
1133 capture_message_ = value;
1134}
1135
1136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001137// --- M e s s a g e ---
1138
1139
1140Local<String> Message::Get() {
1141 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1142 HandleScope scope;
1143 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1144 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1145 Local<String> result = Utils::ToLocal(raw_result);
1146 return scope.Close(result);
1147}
1148
1149
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001150v8::Handle<Value> Message::GetScriptResourceName() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001151 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1152 return Local<String>();
1153 }
1154 HandleScope scope;
1155 i::Handle<i::JSObject> obj =
1156 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1157 // Return this.script.name.
1158 i::Handle<i::JSValue> script =
1159 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1160 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001161 return scope.Close(Utils::ToLocal(resource_name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162}
1163
1164
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001165static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1166 i::Handle<i::Object> recv,
1167 int argc,
1168 i::Object** argv[],
1169 bool* has_pending_exception) {
1170 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1171 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1172 i::Handle<i::JSFunction> fun =
1173 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1174 i::Handle<i::Object> value =
1175 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1176 return value;
1177}
1178
1179
1180static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1181 i::Handle<i::Object> data,
1182 bool* has_pending_exception) {
1183 i::Object** argv[1] = { data.location() };
1184 return CallV8HeapFunction(name,
1185 i::Top::builtins(),
1186 1,
1187 argv,
1188 has_pending_exception);
1189}
1190
1191
1192int Message::GetLineNumber() {
1193 ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
1194 HandleScope scope;
1195 EXCEPTION_PREAMBLE();
1196 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1197 Utils::OpenHandle(this),
1198 &has_pending_exception);
1199 EXCEPTION_BAILOUT_CHECK(0);
1200 return static_cast<int>(result->Number());
1201}
1202
1203
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001204int Message::GetStartPosition() {
1205 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1206 HandleScope scope;
1207
1208 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1209 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1210}
1211
1212
1213int Message::GetEndPosition() {
1214 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1215 HandleScope scope;
1216 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1217 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1218}
1219
1220
1221int Message::GetStartColumn() {
1222 if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
1223 HandleScope scope;
1224 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1225 EXCEPTION_PREAMBLE();
1226 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1227 "GetPositionInLine",
1228 data_obj,
1229 &has_pending_exception);
1230 EXCEPTION_BAILOUT_CHECK(0);
1231 return static_cast<int>(start_col_obj->Number());
1232}
1233
1234
1235int Message::GetEndColumn() {
1236 if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
1237 HandleScope scope;
1238 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1239 EXCEPTION_PREAMBLE();
1240 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1241 "GetPositionInLine",
1242 data_obj,
1243 &has_pending_exception);
1244 EXCEPTION_BAILOUT_CHECK(0);
1245 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1246 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1247 return static_cast<int>(start_col_obj->Number()) + (end - start);
1248}
1249
1250
1251Local<String> Message::GetSourceLine() {
1252 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001253 HandleScope scope;
1254 EXCEPTION_PREAMBLE();
1255 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1256 Utils::OpenHandle(this),
1257 &has_pending_exception);
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001258 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1259 if (result->IsString()) {
1260 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1261 } else {
1262 return Local<String>();
1263 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001264}
1265
1266
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001267void Message::PrintCurrentStackTrace(FILE* out) {
1268 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1269 i::Top::PrintCurrentStackTrace(out);
1270}
1271
1272
1273// --- D a t a ---
1274
1275bool Value::IsUndefined() {
1276 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1277 return Utils::OpenHandle(this)->IsUndefined();
1278}
1279
1280
1281bool Value::IsNull() {
1282 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1283 return Utils::OpenHandle(this)->IsNull();
1284}
1285
1286
1287bool Value::IsTrue() {
1288 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1289 return Utils::OpenHandle(this)->IsTrue();
1290}
1291
1292
1293bool Value::IsFalse() {
1294 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1295 return Utils::OpenHandle(this)->IsFalse();
1296}
1297
1298
1299bool Value::IsFunction() {
1300 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1301 return Utils::OpenHandle(this)->IsJSFunction();
1302}
1303
1304
1305bool Value::IsString() {
1306 if (IsDeadCheck("v8::Value::IsString()")) return false;
1307 return Utils::OpenHandle(this)->IsString();
1308}
1309
1310
1311bool Value::IsArray() {
1312 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1313 return Utils::OpenHandle(this)->IsJSArray();
1314}
1315
1316
1317bool Value::IsObject() {
1318 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1319 return Utils::OpenHandle(this)->IsJSObject();
1320}
1321
1322
1323bool Value::IsNumber() {
1324 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1325 return Utils::OpenHandle(this)->IsNumber();
1326}
1327
1328
1329bool Value::IsBoolean() {
1330 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1331 return Utils::OpenHandle(this)->IsBoolean();
1332}
1333
1334
1335bool Value::IsExternal() {
1336 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1337 return Utils::OpenHandle(this)->IsProxy();
1338}
1339
1340
1341bool Value::IsInt32() {
1342 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1343 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1344 if (obj->IsSmi()) return true;
1345 if (obj->IsNumber()) {
1346 double value = obj->Number();
1347 return i::FastI2D(i::FastD2I(value)) == value;
1348 }
1349 return false;
1350}
1351
1352
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001353bool Value::IsDate() {
1354 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1355 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1356 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1357}
1358
1359
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001360Local<String> Value::ToString() {
1361 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1362 LOG_API("ToString");
1363 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1364 i::Handle<i::Object> str;
1365 if (obj->IsString()) {
1366 str = obj;
1367 } else {
1368 EXCEPTION_PREAMBLE();
1369 str = i::Execution::ToString(obj, &has_pending_exception);
1370 EXCEPTION_BAILOUT_CHECK(Local<String>());
1371 }
1372 return Local<String>(ToApi<String>(str));
1373}
1374
1375
1376Local<String> Value::ToDetailString() {
1377 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1378 LOG_API("ToDetailString");
1379 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1380 i::Handle<i::Object> str;
1381 if (obj->IsString()) {
1382 str = obj;
1383 } else {
1384 EXCEPTION_PREAMBLE();
1385 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1386 EXCEPTION_BAILOUT_CHECK(Local<String>());
1387 }
1388 return Local<String>(ToApi<String>(str));
1389}
1390
1391
1392Local<v8::Object> Value::ToObject() {
1393 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1394 LOG_API("ToObject");
1395 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1396 i::Handle<i::Object> val;
1397 if (obj->IsJSObject()) {
1398 val = obj;
1399 } else {
1400 EXCEPTION_PREAMBLE();
1401 val = i::Execution::ToObject(obj, &has_pending_exception);
1402 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1403 }
1404 return Local<v8::Object>(ToApi<Object>(val));
1405}
1406
1407
1408Local<Boolean> Value::ToBoolean() {
1409 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1410 LOG_API("ToBoolean");
1411 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1412 i::Handle<i::Object> val =
1413 obj->IsBoolean() ? obj : i::Execution::ToBoolean(obj);
1414 return Local<Boolean>(ToApi<Boolean>(val));
1415}
1416
1417
1418Local<Number> Value::ToNumber() {
1419 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1420 LOG_API("ToNumber");
1421 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1422 i::Handle<i::Object> num;
1423 if (obj->IsNumber()) {
1424 num = obj;
1425 } else {
1426 EXCEPTION_PREAMBLE();
1427 num = i::Execution::ToNumber(obj, &has_pending_exception);
1428 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1429 }
1430 return Local<Number>(ToApi<Number>(num));
1431}
1432
1433
1434Local<Integer> Value::ToInteger() {
1435 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1436 LOG_API("ToInteger");
1437 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1438 i::Handle<i::Object> num;
1439 if (obj->IsSmi()) {
1440 num = obj;
1441 } else {
1442 EXCEPTION_PREAMBLE();
1443 num = i::Execution::ToInteger(obj, &has_pending_exception);
1444 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1445 }
1446 return Local<Integer>(ToApi<Integer>(num));
1447}
1448
1449
1450External* External::Cast(v8::Value* that) {
1451 if (IsDeadCheck("v8::External::Cast()")) return 0;
1452 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1453 ApiCheck(obj->IsProxy(),
1454 "v8::External::Cast()",
1455 "Could not convert to external");
1456 return static_cast<External*>(that);
1457}
1458
1459
1460v8::Object* v8::Object::Cast(Value* that) {
1461 if (IsDeadCheck("v8::Object::Cast()")) return 0;
1462 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1463 ApiCheck(obj->IsJSObject(),
1464 "v8::Object::Cast()",
1465 "Could not convert to object");
1466 return static_cast<v8::Object*>(that);
1467}
1468
1469
1470v8::Function* v8::Function::Cast(Value* that) {
1471 if (IsDeadCheck("v8::Function::Cast()")) return 0;
1472 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1473 ApiCheck(obj->IsJSFunction(),
1474 "v8::Function::Cast()",
1475 "Could not convert to function");
1476 return static_cast<v8::Function*>(that);
1477}
1478
1479
1480v8::String* v8::String::Cast(v8::Value* that) {
1481 if (IsDeadCheck("v8::String::Cast()")) return 0;
1482 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1483 ApiCheck(obj->IsString(),
1484 "v8::String::Cast()",
1485 "Could not convert to string");
1486 return static_cast<v8::String*>(that);
1487}
1488
1489
1490v8::Number* v8::Number::Cast(v8::Value* that) {
1491 if (IsDeadCheck("v8::Number::Cast()")) return 0;
1492 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1493 ApiCheck(obj->IsNumber(),
1494 "v8::Number::Cast()",
1495 "Could not convert to number");
1496 return static_cast<v8::Number*>(that);
1497}
1498
1499
1500v8::Integer* v8::Integer::Cast(v8::Value* that) {
1501 if (IsDeadCheck("v8::Integer::Cast()")) return 0;
1502 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1503 ApiCheck(obj->IsNumber(),
1504 "v8::Integer::Cast()",
1505 "Could not convert to number");
1506 return static_cast<v8::Integer*>(that);
1507}
1508
1509
1510v8::Array* v8::Array::Cast(Value* that) {
1511 if (IsDeadCheck("v8::Array::Cast()")) return 0;
1512 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1513 ApiCheck(obj->IsJSArray(),
1514 "v8::Array::Cast()",
1515 "Could not convert to array");
1516 return static_cast<v8::Array*>(that);
1517}
1518
1519
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001520v8::Date* v8::Date::Cast(v8::Value* that) {
1521 if (IsDeadCheck("v8::Date::Cast()")) return 0;
1522 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1523 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1524 "v8::Date::Cast()",
1525 "Could not convert to date");
1526 return static_cast<v8::Date*>(that);
1527}
1528
1529
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001530bool Value::BooleanValue() {
1531 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1532 LOG_API("BooleanValue");
1533 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1534 i::Handle<i::Object> value =
1535 obj->IsBoolean() ? obj : i::Execution::ToBoolean(obj);
1536 return value->IsTrue();
1537}
1538
1539
1540double Value::NumberValue() {
1541 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1542 LOG_API("NumberValue");
1543 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1544 i::Handle<i::Object> num;
1545 if (obj->IsNumber()) {
1546 num = obj;
1547 } else {
1548 EXCEPTION_PREAMBLE();
1549 num = i::Execution::ToNumber(obj, &has_pending_exception);
1550 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1551 }
1552 return num->Number();
1553}
1554
1555
1556int64_t Value::IntegerValue() {
1557 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1558 LOG_API("IntegerValue");
1559 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1560 i::Handle<i::Object> num;
1561 if (obj->IsNumber()) {
1562 num = obj;
1563 } else {
1564 EXCEPTION_PREAMBLE();
1565 num = i::Execution::ToInteger(obj, &has_pending_exception);
1566 EXCEPTION_BAILOUT_CHECK(0);
1567 }
1568 if (num->IsSmi()) {
1569 return i::Smi::cast(*num)->value();
1570 } else {
1571 return static_cast<int64_t>(num->Number());
1572 }
1573}
1574
1575
1576Local<Int32> Value::ToInt32() {
1577 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1578 LOG_API("ToInt32");
1579 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1580 i::Handle<i::Object> num;
1581 if (obj->IsSmi()) {
1582 num = obj;
1583 } else {
1584 EXCEPTION_PREAMBLE();
1585 num = i::Execution::ToInt32(obj, &has_pending_exception);
1586 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1587 }
1588 return Local<Int32>(ToApi<Int32>(num));
1589}
1590
1591
1592Local<Uint32> Value::ToUint32() {
1593 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1594 LOG_API("ToUInt32");
1595 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1596 i::Handle<i::Object> num;
1597 if (obj->IsSmi()) {
1598 num = obj;
1599 } else {
1600 EXCEPTION_PREAMBLE();
1601 num = i::Execution::ToUint32(obj, &has_pending_exception);
1602 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1603 }
1604 return Local<Uint32>(ToApi<Uint32>(num));
1605}
1606
1607
1608Local<Uint32> Value::ToArrayIndex() {
1609 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
1610 LOG_API("ToArrayIndex");
1611 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1612 if (obj->IsSmi()) {
1613 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
1614 return Local<Uint32>();
1615 }
1616 EXCEPTION_PREAMBLE();
1617 i::Handle<i::Object> string_obj =
1618 i::Execution::ToString(obj, &has_pending_exception);
1619 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1620 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
1621 uint32_t index;
1622 if (str->AsArrayIndex(&index)) {
1623 i::Handle<i::Object> value;
1624 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
1625 value = i::Handle<i::Object>(i::Smi::FromInt(index));
1626 } else {
1627 value = i::Factory::NewNumber(index);
1628 }
1629 return Utils::Uint32ToLocal(value);
1630 }
1631 return Local<Uint32>();
1632}
1633
1634
1635int32_t Value::Int32Value() {
1636 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
1637 LOG_API("Int32Value");
1638 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1639 if (obj->IsSmi()) {
1640 return i::Smi::cast(*obj)->value();
1641 } else {
1642 LOG_API("Int32Value (slow)");
1643 EXCEPTION_PREAMBLE();
1644 i::Handle<i::Object> num =
1645 i::Execution::ToInt32(obj, &has_pending_exception);
1646 EXCEPTION_BAILOUT_CHECK(0);
1647 if (num->IsSmi()) {
1648 return i::Smi::cast(*num)->value();
1649 } else {
1650 return static_cast<int32_t>(num->Number());
1651 }
1652 }
1653}
1654
1655
1656bool Value::Equals(Handle<Value> that) {
1657 if (IsDeadCheck("v8::Value::Equals()")
1658 || EmptyCheck("v8::Value::Equals()", this)
1659 || EmptyCheck("v8::Value::Equals()", that))
1660 return false;
1661 LOG_API("Equals");
1662 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1663 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1664 i::Object** args[1] = { other.location() };
1665 EXCEPTION_PREAMBLE();
1666 i::Handle<i::Object> result =
1667 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
1668 EXCEPTION_BAILOUT_CHECK(false);
1669 return *result == i::Smi::FromInt(i::EQUAL);
1670}
1671
1672
1673bool Value::StrictEquals(Handle<Value> that) {
1674 if (IsDeadCheck("v8::Value::StrictEquals()")
1675 || EmptyCheck("v8::Value::StrictEquals()", this)
1676 || EmptyCheck("v8::Value::StrictEquals()", that))
1677 return false;
1678 LOG_API("StrictEquals");
1679 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1680 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1681 // Must check HeapNumber first, since NaN !== NaN.
1682 if (obj->IsHeapNumber()) {
1683 if (!other->IsNumber()) return false;
1684 double x = obj->Number();
1685 double y = other->Number();
1686 // Must check explicitly for NaN:s on Windows, but -0 works fine.
1687 return x == y && !isnan(x) && !isnan(y);
1688 } else if (*obj == *other) { // Also covers Booleans.
1689 return true;
1690 } else if (obj->IsSmi()) {
1691 return other->IsNumber() && obj->Number() == other->Number();
1692 } else if (obj->IsString()) {
1693 return other->IsString() &&
1694 i::String::cast(*obj)->Equals(i::String::cast(*other));
1695 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
1696 return other->IsUndefined() || other->IsUndetectableObject();
1697 } else {
1698 return false;
1699 }
1700}
1701
1702
1703uint32_t Value::Uint32Value() {
1704 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
1705 LOG_API("Uint32Value");
1706 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1707 if (obj->IsSmi()) {
1708 return i::Smi::cast(*obj)->value();
1709 } else {
1710 EXCEPTION_PREAMBLE();
1711 i::Handle<i::Object> num =
1712 i::Execution::ToUint32(obj, &has_pending_exception);
1713 EXCEPTION_BAILOUT_CHECK(0);
1714 if (num->IsSmi()) {
1715 return i::Smi::cast(*num)->value();
1716 } else {
1717 return static_cast<uint32_t>(num->Number());
1718 }
1719 }
1720}
1721
1722
1723bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001724 v8::PropertyAttribute attribs) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725 ON_BAILOUT("v8::Object::Set()", return false);
1726 i::Handle<i::Object> self = Utils::OpenHandle(this);
1727 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1728 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1729 EXCEPTION_PREAMBLE();
1730 i::Handle<i::Object> obj = i::SetProperty(
1731 self,
1732 key_obj,
1733 value_obj,
1734 static_cast<PropertyAttributes>(attribs));
1735 has_pending_exception = obj.is_null();
1736 EXCEPTION_BAILOUT_CHECK(false);
1737 return true;
1738}
1739
1740
1741Local<Value> v8::Object::Get(v8::Handle<Value> key) {
1742 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
1743 i::Handle<i::Object> self = Utils::OpenHandle(this);
1744 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1745 EXCEPTION_PREAMBLE();
1746 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
1747 has_pending_exception = result.is_null();
1748 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1749 return Utils::ToLocal(result);
1750}
1751
1752
1753Local<Value> v8::Object::GetPrototype() {
1754 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
1755 i::Handle<i::Object> self = Utils::OpenHandle(this);
1756 i::Handle<i::Object> result = i::GetPrototype(self);
1757 return Utils::ToLocal(result);
1758}
1759
1760
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001761Local<Array> v8::Object::GetPropertyNames() {
1762 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
1763 v8::HandleScope scope;
1764 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1765 i::Handle<i::FixedArray> value = i::GetKeysInFixedArrayFor(self);
1766 // Because we use caching to speed up enumeration it is important
1767 // to never change the result of the basic enumeration function so
1768 // we clone the result.
1769 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
1770 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
1771 return scope.Close(Utils::ToLocal(result));
1772}
1773
1774
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001775Local<String> v8::Object::ObjectProtoToString() {
1776 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
1777 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1778
1779 i::Handle<i::Object> name(self->class_name());
1780
1781 // Native implementation of Object.prototype.toString (v8natives.js):
1782 // var c = %ClassOf(this);
1783 // if (c === 'Arguments') c = 'Object';
1784 // return "[object " + c + "]";
1785
1786 if (!name->IsString()) {
1787 return v8::String::New("[object ]");
1788
1789 } else {
1790 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
1791 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
1792 return v8::String::New("[object Object]");
1793
1794 } else {
1795 const char* prefix = "[object ";
1796 Local<String> str = Utils::ToLocal(class_name);
1797 const char* postfix = "]";
1798
1799 size_t prefix_len = strlen(prefix);
1800 size_t str_len = str->Length();
1801 size_t postfix_len = strlen(postfix);
1802
1803 size_t buf_len = prefix_len + str_len + postfix_len;
1804 char* buf = i::NewArray<char>(buf_len);
1805
1806 // Write prefix.
1807 char* ptr = buf;
1808 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
1809 ptr += prefix_len;
1810
1811 // Write real content.
1812 str->WriteAscii(ptr, 0, str_len);
1813 ptr += str_len;
1814
1815 // Write postfix.
1816 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
1817
1818 // Copy the buffer into a heap-allocated string and return it.
1819 Local<String> result = v8::String::New(buf, buf_len);
1820 i::DeleteArray(buf);
1821 return result;
1822 }
1823 }
1824}
1825
1826
1827bool v8::Object::Delete(v8::Handle<String> key) {
1828 ON_BAILOUT("v8::Object::Delete()", return false);
1829 HandleScope scope;
1830 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1831 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
1832 return i::DeleteProperty(self, key_obj)->IsTrue();
1833}
1834
1835
1836bool v8::Object::Has(v8::Handle<String> key) {
1837 ON_BAILOUT("v8::Object::Has()", return false);
1838 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1839 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
1840 return self->HasProperty(*key_obj);
1841}
1842
1843
1844bool v8::Object::Delete(uint32_t index) {
1845 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
1846 HandleScope scope;
1847 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1848 return i::DeleteElement(self, index)->IsTrue();
1849}
1850
1851
1852bool v8::Object::Has(uint32_t index) {
1853 ON_BAILOUT("v8::Object::HasProperty()", return false);
1854 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1855 return self->HasElement(index);
1856}
1857
1858
1859bool v8::Object::HasRealNamedProperty(Handle<String> key) {
1860 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
1861 return Utils::OpenHandle(this)->HasRealNamedProperty(
1862 *Utils::OpenHandle(*key));
1863}
1864
1865
1866bool v8::Object::HasRealIndexedProperty(uint32_t index) {
1867 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
1868 return Utils::OpenHandle(this)->HasRealElementProperty(index);
1869}
1870
1871
1872bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
1873 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
1874 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
1875 *Utils::OpenHandle(*key));
1876}
1877
1878
1879bool v8::Object::HasNamedLookupInterceptor() {
1880 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
1881 return Utils::OpenHandle(this)->HasNamedInterceptor();
1882}
1883
1884
1885bool v8::Object::HasIndexedLookupInterceptor() {
1886 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
1887 return Utils::OpenHandle(this)->HasIndexedInterceptor();
1888}
1889
1890
1891Handle<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
1892 Handle<String> key) {
1893 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
1894 return Local<Value>());
1895 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
1896 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
1897 i::LookupResult lookup;
1898 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
1899 if (lookup.IsValid()) {
1900 PropertyAttributes attributes;
1901 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
1902 &lookup,
1903 *key_obj,
1904 &attributes));
1905 return Utils::ToLocal(result);
1906 }
v8.team.kasperl727e9952008-09-02 14:56:44 +00001907 return Local<Value>(); // No real property was found in prototype chain.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001908}
1909
1910
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001911// Turns on access checks by copying the map and setting the check flag.
1912// Because the object gets a new map, existing inline cache caching
1913// the old map of this object will fail.
1914void v8::Object::TurnOnAccessCheck() {
1915 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
1916 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
1917
1918 i::Handle<i::Map> new_map =
1919 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
ager@chromium.org870a0b62008-11-04 11:43:05 +00001920 new_map->set_is_access_check_needed(true);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001921 obj->set_map(*new_map);
1922}
1923
1924
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001925Local<v8::Object> Function::NewInstance() {
1926 return NewInstance(0, NULL);
1927}
1928
1929
1930Local<v8::Object> Function::NewInstance(int argc,
1931 v8::Handle<v8::Value> argv[]) {
1932 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
1933 LOG_API("Function::NewInstance");
1934 HandleScope scope;
1935 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
1936 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
1937 i::Object*** args = reinterpret_cast<i::Object***>(argv);
1938 EXCEPTION_PREAMBLE();
1939 i::Handle<i::Object> returned =
1940 i::Execution::New(function, argc, args, &has_pending_exception);
1941 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1942 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
1943}
1944
1945
1946Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
1947 v8::Handle<v8::Value> argv[]) {
1948 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
1949 LOG_API("Function::Call");
1950 i::Object* raw_result = NULL;
1951 {
1952 HandleScope scope;
1953 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1954 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
1955 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
1956 i::Object*** args = reinterpret_cast<i::Object***>(argv);
1957 EXCEPTION_PREAMBLE();
1958 i::Handle<i::Object> returned =
1959 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
1960 EXCEPTION_BAILOUT_CHECK(Local<Object>());
1961 raw_result = *returned;
1962 }
1963 i::Handle<i::Object> result(raw_result);
1964 return Utils::ToLocal(result);
1965}
1966
1967
1968void Function::SetName(v8::Handle<v8::String> name) {
1969 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
1970 func->shared()->set_name(*Utils::OpenHandle(*name));
1971}
1972
1973
1974Handle<Value> Function::GetName() {
1975 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
1976 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
1977}
1978
1979
1980int String::Length() {
1981 if (IsDeadCheck("v8::String::Length()")) return 0;
1982 return Utils::OpenHandle(this)->length();
1983}
1984
1985
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001986int String::Utf8Length() {
1987 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
1988 return Utils::OpenHandle(this)->Utf8Length();
1989}
1990
1991
1992int String::WriteUtf8(char* buffer, int capacity) {
1993 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
1994 LOG_API("String::WriteUtf8");
1995 i::Handle<i::String> str = Utils::OpenHandle(this);
1996 write_input_buffer.Reset(0, *str);
1997 int len = str->length();
1998 // Encode the first K - 3 bytes directly into the buffer since we
1999 // know there's room for them. If no capacity is given we copy all
2000 // of them here.
2001 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2002 int i;
2003 int pos = 0;
2004 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2005 i::uc32 c = write_input_buffer.GetNext();
2006 int written = unibrow::Utf8::Encode(buffer + pos, c);
2007 pos += written;
2008 }
2009 if (i < len) {
2010 // For the last characters we need to check the length for each one
2011 // because they may be longer than the remaining space in the
2012 // buffer.
2013 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2014 for (; i < len && pos < capacity; i++) {
2015 i::uc32 c = write_input_buffer.GetNext();
2016 int written = unibrow::Utf8::Encode(intermediate, c);
2017 if (pos + written <= capacity) {
2018 for (int j = 0; j < written; j++)
2019 buffer[pos + j] = intermediate[j];
2020 pos += written;
2021 } else {
2022 // We've reached the end of the buffer
2023 break;
2024 }
2025 }
2026 }
2027 if (i == len && (capacity == -1 || pos < capacity))
2028 buffer[pos++] = '\0';
2029 return pos;
2030}
2031
2032
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002033int String::WriteAscii(char* buffer, int start, int length) {
2034 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2035 LOG_API("String::WriteAscii");
2036 ASSERT(start >= 0 && length >= -1);
2037 i::Handle<i::String> str = Utils::OpenHandle(this);
2038 // Flatten the string for efficiency. This applies whether we are
2039 // using StringInputBuffer or Get(i) to access the characters.
ager@chromium.org870a0b62008-11-04 11:43:05 +00002040 str->TryFlatten(i::StringShape(*str));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002041 int end = length;
2042 if ( (length == -1) || (length > str->length() - start) )
2043 end = str->length() - start;
2044 if (end < 0) return 0;
2045 write_input_buffer.Reset(start, *str);
2046 int i;
2047 for (i = 0; i < end; i++) {
2048 char c = static_cast<char>(write_input_buffer.GetNext());
2049 if (c == '\0') c = ' ';
2050 buffer[i] = c;
2051 }
2052 if (length == -1 || i < length)
2053 buffer[i] = '\0';
2054 return i;
2055}
2056
2057
2058int String::Write(uint16_t* buffer, int start, int length) {
2059 if (IsDeadCheck("v8::String::Write()")) return 0;
2060 LOG_API("String::Write");
2061 ASSERT(start >= 0 && length >= -1);
2062 i::Handle<i::String> str = Utils::OpenHandle(this);
2063 // Flatten the string for efficiency. This applies whether we are
2064 // using StringInputBuffer or Get(i) to access the characters.
ager@chromium.org870a0b62008-11-04 11:43:05 +00002065 str->TryFlatten(i::StringShape(*str));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066 int end = length;
2067 if ( (length == -1) || (length > str->length() - start) )
2068 end = str->length() - start;
2069 if (end < 0) return 0;
2070 write_input_buffer.Reset(start, *str);
2071 int i;
2072 for (i = 0; i < end; i++)
2073 buffer[i] = write_input_buffer.GetNext();
2074 if (length == -1 || i < length)
2075 buffer[i] = '\0';
2076 return i;
2077}
2078
2079
2080bool v8::String::IsExternal() {
2081 EnsureInitialized("v8::String::IsExternal()");
2082 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.org870a0b62008-11-04 11:43:05 +00002083 i::StringShape shape(*str);
2084 return shape.IsExternalTwoByte();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002085}
2086
2087
2088bool v8::String::IsExternalAscii() {
2089 EnsureInitialized("v8::String::IsExternalAscii()");
2090 i::Handle<i::String> str = Utils::OpenHandle(this);
ager@chromium.org870a0b62008-11-04 11:43:05 +00002091 i::StringShape shape(*str);
2092 return shape.IsExternalAscii();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002093}
2094
2095
2096v8::String::ExternalStringResource* v8::String::GetExternalStringResource() {
2097 EnsureInitialized("v8::String::GetExternalStringResource()");
2098 i::Handle<i::String> str = Utils::OpenHandle(this);
2099 ASSERT(str->IsExternalTwoByteString());
2100 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2101 return reinterpret_cast<ExternalStringResource*>(resource);
2102}
2103
2104
2105v8::String::ExternalAsciiStringResource*
2106 v8::String::GetExternalAsciiStringResource() {
2107 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2108 i::Handle<i::String> str = Utils::OpenHandle(this);
2109 ASSERT(str->IsExternalAsciiString());
2110 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2111 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2112}
2113
2114
2115double Number::Value() {
2116 if (IsDeadCheck("v8::Number::Value()")) return 0;
2117 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2118 return obj->Number();
2119}
2120
2121
2122bool Boolean::Value() {
2123 if (IsDeadCheck("v8::Boolean::Value()")) return false;
2124 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2125 return obj->IsTrue();
2126}
2127
2128
2129int64_t Integer::Value() {
2130 if (IsDeadCheck("v8::Integer::Value()")) return 0;
2131 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2132 if (obj->IsSmi()) {
2133 return i::Smi::cast(*obj)->value();
2134 } else {
2135 return static_cast<int64_t>(obj->Number());
2136 }
2137}
2138
2139
2140int32_t Int32::Value() {
2141 if (IsDeadCheck("v8::Int32::Value()")) return 0;
2142 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2143 if (obj->IsSmi()) {
2144 return i::Smi::cast(*obj)->value();
2145 } else {
2146 return static_cast<int32_t>(obj->Number());
2147 }
2148}
2149
2150
2151void* External::Value() {
2152 if (IsDeadCheck("v8::External::Value()")) return 0;
2153 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2154 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
2155}
2156
2157
2158int v8::Object::InternalFieldCount() {
2159 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2160 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2161 return obj->GetInternalFieldCount();
2162}
2163
2164
kasper.lund212ac232008-07-16 07:07:30 +00002165Local<Value> v8::Object::GetInternalField(int index) {
2166 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002168 if (!ApiCheck(index < obj->GetInternalFieldCount(),
kasper.lund212ac232008-07-16 07:07:30 +00002169 "v8::Object::GetInternalField()",
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002170 "Reading internal field out of bounds")) {
2171 return Local<Value>();
2172 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002173 i::Handle<i::Object> value(obj->GetInternalField(index));
2174 return Utils::ToLocal(value);
2175}
2176
2177
kasper.lund212ac232008-07-16 07:07:30 +00002178void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2179 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002180 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002181 if (!ApiCheck(index < obj->GetInternalFieldCount(),
kasper.lund212ac232008-07-16 07:07:30 +00002182 "v8::Object::SetInternalField()",
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002183 "Writing internal field out of bounds")) {
2184 return;
2185 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186 i::Handle<i::Object> val = Utils::OpenHandle(*value);
2187 obj->SetInternalField(index, *val);
2188}
2189
2190
2191// --- E n v i r o n m e n t ---
2192
2193bool v8::V8::Initialize() {
2194 if (i::V8::HasBeenSetup()) return true;
2195 HandleScope scope;
2196 if (i::Snapshot::Initialize()) {
2197 i::Serializer::disable();
2198 return true;
2199 } else {
2200 return i::V8::Initialize(NULL);
2201 }
2202}
2203
2204
kasper.lund7276f142008-07-30 08:49:36 +00002205const char* v8::V8::GetVersion() {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002206 return "0.4.5";
kasper.lund7276f142008-07-30 08:49:36 +00002207}
2208
2209
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002210static i::Handle<i::FunctionTemplateInfo>
2211 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
2212 if (templ->constructor()->IsUndefined()) {
2213 Local<FunctionTemplate> constructor = FunctionTemplate::New();
2214 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
2215 templ->set_constructor(*Utils::OpenHandle(*constructor));
2216 }
2217 return i::Handle<i::FunctionTemplateInfo>(
2218 i::FunctionTemplateInfo::cast(templ->constructor()));
2219}
2220
2221
2222Persistent<Context> v8::Context::New(
2223 v8::ExtensionConfiguration* extensions,
2224 v8::Handle<ObjectTemplate> global_template,
2225 v8::Handle<Value> global_object) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002226 EnsureInitialized("v8::Context::New()");
2227 LOG_API("Context::New");
2228 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002230 // Make sure that the global_template has a constructor.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002231 if (!global_template.IsEmpty()) {
2232 i::Handle<i::FunctionTemplateInfo> constructor =
2233 EnsureConstructor(Utils::OpenHandle(*global_template));
2234
2235 // Create a fresh template for global proxy object.
2236 Local<ObjectTemplate> proxy_template = ObjectTemplate::New();
2237
2238 i::Handle<i::FunctionTemplateInfo> proxy_constructor =
2239 EnsureConstructor(Utils::OpenHandle(*proxy_template));
2240
2241 // Set the global template to be the prototype template
2242 // of global proxy template.
2243 proxy_constructor->set_prototype_template(
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002244 *Utils::OpenHandle(*global_template));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002245
2246 // Migrate security handlers from global_template to proxy_template.
2247 if (!constructor->access_check_info()->IsUndefined()) {
2248 proxy_constructor->set_access_check_info(
2249 constructor->access_check_info());
2250 proxy_constructor->set_needs_access_check(true);
2251
2252 // Remove access check info from global_template.
2253 constructor->set_needs_access_check(false);
2254 constructor->set_access_check_info(i::Heap::undefined_value());
2255 }
2256
2257 global_template = proxy_template;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002258 }
2259
2260 i::Handle<i::Context> env = i::Bootstrapper::CreateEnvironment(
2261 Utils::OpenHandle(*global_object),
2262 global_template, extensions);
2263 if (!ApiCheck(!env.is_null(),
2264 "v8::Context::New()",
2265 "Could not initialize environment"))
2266 return Persistent<Context>();
2267 return Persistent<Context>(Utils::ToLocal(env));
2268}
2269
2270
2271void v8::Context::SetSecurityToken(Handle<Value> token) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002272 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002273 i::Handle<i::Context> env = Utils::OpenHandle(this);
2274 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002275 env->set_security_token(*token_handle);
2276}
2277
2278
2279void v8::Context::UseDefaultSecurityToken() {
2280 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
2281 i::Handle<i::Context> env = Utils::OpenHandle(this);
2282 env->set_security_token(env->global());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002283}
2284
2285
2286Handle<Value> v8::Context::GetSecurityToken() {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002287 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002288 i::Handle<i::Context> env = Utils::OpenHandle(this);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002289 i::Object* security_token = env->security_token();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002290 i::Handle<i::Object> token_handle(security_token);
2291 return Utils::ToLocal(token_handle);
2292}
2293
2294
2295bool Context::HasOutOfMemoryException() {
2296 i::Handle<i::Context> env = Utils::OpenHandle(this);
2297 return env->has_out_of_memory();
2298}
2299
2300
2301bool Context::InContext() {
2302 return i::Top::context() != NULL;
2303}
2304
2305
kasper.lund44510672008-07-25 07:37:58 +00002306v8::Local<v8::Context> Context::GetEntered() {
2307 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
2308 i::Handle<i::Object> last = thread_local.LastEnteredContext();
2309 if (last.is_null()) return Local<Context>();
2310 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
2311 return Utils::ToLocal(context);
2312}
2313
2314
2315v8::Local<v8::Context> Context::GetCurrent() {
2316 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002317 i::Handle<i::Context> context(i::Top::global_context());
2318 return Utils::ToLocal(context);
2319}
2320
2321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002322v8::Local<v8::Object> Context::Global() {
2323 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
2324 i::Object** ctx = reinterpret_cast<i::Object**>(this);
2325 i::Handle<i::Context> context =
2326 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002327 i::Handle<i::Object> global(context->global_proxy());
2328 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
2329}
2330
2331
2332void Context::DetachGlobal() {
2333 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
2334 i::Object** ctx = reinterpret_cast<i::Object**>(this);
2335 i::Handle<i::Context> context =
2336 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2337 i::Bootstrapper::DetachGlobal(context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002338}
2339
2340
2341Local<v8::Object> ObjectTemplate::NewInstance() {
2342 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
2343 LOG_API("ObjectTemplate::NewInstance");
2344 EXCEPTION_PREAMBLE();
2345 i::Handle<i::Object> obj =
2346 i::Execution::InstantiateObject(Utils::OpenHandle(this),
2347 &has_pending_exception);
2348 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2349 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
2350}
2351
2352
2353Local<v8::Function> FunctionTemplate::GetFunction() {
2354 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
2355 return Local<v8::Function>());
2356 LOG_API("FunctionTemplate::GetFunction");
2357 EXCEPTION_PREAMBLE();
2358 i::Handle<i::Object> obj =
2359 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
2360 &has_pending_exception);
2361 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
2362 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
2363}
2364
2365
2366bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
2367 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
2368 i::Object* obj = *Utils::OpenHandle(*value);
2369 return obj->IsInstanceOf(*Utils::OpenHandle(this));
2370}
2371
2372
2373Local<External> v8::External::New(void* data) {
2374 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
2375 LOG_API("External::New");
2376 EnsureInitialized("v8::External::New()");
2377 i::Handle<i::Proxy> obj = i::Factory::NewProxy(static_cast<i::Address>(data));
2378 return Utils::ToLocal(obj);
2379}
2380
2381
2382Local<String> v8::String::New(const char* data, int length) {
2383 EnsureInitialized("v8::String::New()");
2384 LOG_API("String::New(char)");
2385 if (length == -1) length = strlen(data);
2386 i::Handle<i::String> result =
2387 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2388 return Utils::ToLocal(result);
2389}
2390
2391
2392Local<String> v8::String::NewUndetectable(const char* data, int length) {
2393 EnsureInitialized("v8::String::NewUndetectable()");
2394 LOG_API("String::NewUndetectable(char)");
2395 if (length == -1) length = strlen(data);
2396 i::Handle<i::String> result =
2397 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
2398 result->MarkAsUndetectable();
2399 return Utils::ToLocal(result);
2400}
2401
2402
2403static int TwoByteStringLength(const uint16_t* data) {
2404 int length = 0;
2405 while (data[length] != '\0') length++;
2406 return length;
2407}
2408
2409
2410Local<String> v8::String::New(const uint16_t* data, int length) {
2411 EnsureInitialized("v8::String::New()");
2412 LOG_API("String::New(uint16_)");
2413 if (length == -1) length = TwoByteStringLength(data);
2414 i::Handle<i::String> result =
2415 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2416 return Utils::ToLocal(result);
2417}
2418
2419
2420Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
2421 EnsureInitialized("v8::String::NewUndetectable()");
2422 LOG_API("String::NewUndetectable(uint16_)");
2423 if (length == -1) length = TwoByteStringLength(data);
2424 i::Handle<i::String> result =
2425 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
2426 result->MarkAsUndetectable();
2427 return Utils::ToLocal(result);
2428}
2429
2430
2431i::Handle<i::String> NewExternalStringHandle(
2432 v8::String::ExternalStringResource* resource) {
2433 i::Handle<i::String> result =
2434 i::Factory::NewExternalStringFromTwoByte(resource);
2435 return result;
2436}
2437
2438
2439i::Handle<i::String> NewExternalAsciiStringHandle(
2440 v8::String::ExternalAsciiStringResource* resource) {
2441 i::Handle<i::String> result =
2442 i::Factory::NewExternalStringFromAscii(resource);
2443 return result;
2444}
2445
2446
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002447static void DisposeExternalString(v8::Persistent<v8::Value> obj,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002448 void* parameter) {
2449 v8::String::ExternalStringResource* resource =
2450 reinterpret_cast<v8::String::ExternalStringResource*>(parameter);
2451 const size_t total_size = resource->length() * sizeof(*resource->data());
2452 i::Counters::total_external_string_memory.Decrement(total_size);
2453 delete resource;
2454 obj.Dispose();
2455}
2456
2457
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002458static void DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002459 void* parameter) {
2460 v8::String::ExternalAsciiStringResource* resource =
2461 reinterpret_cast<v8::String::ExternalAsciiStringResource*>(parameter);
2462 const size_t total_size = resource->length() * sizeof(*resource->data());
2463 i::Counters::total_external_string_memory.Decrement(total_size);
2464 delete resource;
2465 obj.Dispose();
2466}
2467
2468
2469Local<String> v8::String::NewExternal(
2470 v8::String::ExternalStringResource* resource) {
2471 EnsureInitialized("v8::String::NewExternal()");
2472 LOG_API("String::NewExternal");
2473 const size_t total_size = resource->length() * sizeof(*resource->data());
2474 i::Counters::total_external_string_memory.Increment(total_size);
2475 i::Handle<i::String> result = NewExternalStringHandle(resource);
2476 i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
2477 i::GlobalHandles::MakeWeak(handle.location(),
2478 resource,
2479 &DisposeExternalString);
2480 return Utils::ToLocal(result);
2481}
2482
2483
2484Local<String> v8::String::NewExternal(
2485 v8::String::ExternalAsciiStringResource* resource) {
2486 EnsureInitialized("v8::String::NewExternal()");
2487 LOG_API("String::NewExternal");
2488 const size_t total_size = resource->length() * sizeof(*resource->data());
2489 i::Counters::total_external_string_memory.Increment(total_size);
2490 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
2491 i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
2492 i::GlobalHandles::MakeWeak(handle.location(),
2493 resource,
2494 &DisposeExternalAsciiString);
2495 return Utils::ToLocal(result);
2496}
2497
2498
2499Local<v8::Object> v8::Object::New() {
2500 EnsureInitialized("v8::Object::New()");
2501 LOG_API("Object::New");
2502 i::Handle<i::JSObject> obj =
2503 i::Factory::NewJSObject(i::Top::object_function());
2504 return Utils::ToLocal(obj);
2505}
2506
2507
2508Local<v8::Value> v8::Date::New(double time) {
2509 EnsureInitialized("v8::Date::New()");
2510 LOG_API("Date::New");
2511 EXCEPTION_PREAMBLE();
2512 i::Handle<i::Object> obj =
2513 i::Execution::NewDate(time, &has_pending_exception);
2514 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
2515 return Utils::ToLocal(obj);
2516}
2517
2518
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002519double v8::Date::NumberValue() {
2520 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
2521 LOG_API("Date::NumberValue");
2522 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2523 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
2524 return jsvalue->value()->Number();
2525}
2526
2527
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002528Local<v8::Array> v8::Array::New(int length) {
2529 EnsureInitialized("v8::Array::New()");
2530 LOG_API("Array::New");
2531 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
2532 return Utils::ToLocal(obj);
2533}
2534
2535
2536uint32_t v8::Array::Length() {
2537 if (IsDeadCheck("v8::Array::Length()")) return 0;
2538 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
2539 i::Object* length = obj->length();
2540 if (length->IsSmi()) {
2541 return i::Smi::cast(length)->value();
2542 } else {
2543 return static_cast<uint32_t>(length->Number());
2544 }
2545}
2546
2547
2548Local<String> v8::String::NewSymbol(const char* data, int length) {
2549 EnsureInitialized("v8::String::NewSymbol()");
2550 LOG_API("String::NewSymbol(char)");
2551 if (length == -1) length = strlen(data);
2552 i::Handle<i::String> result =
2553 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
2554 return Utils::ToLocal(result);
2555}
2556
2557
2558Local<Number> v8::Number::New(double value) {
2559 EnsureInitialized("v8::Number::New()");
2560 i::Handle<i::Object> result = i::Factory::NewNumber(value);
2561 return Utils::NumberToLocal(result);
2562}
2563
2564
2565Local<Integer> v8::Integer::New(int32_t value) {
2566 EnsureInitialized("v8::Integer::New()");
2567 if (i::Smi::IsValid(value)) {
2568 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
2569 }
2570 i::Handle<i::Object> result = i::Factory::NewNumber(value);
2571 return Utils::IntegerToLocal(result);
2572}
2573
2574
2575void V8::IgnoreOutOfMemoryException() {
2576 thread_local.SetIgnoreOutOfMemory(true);
2577}
2578
2579
2580bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
2581 EnsureInitialized("v8::V8::AddMessageListener()");
2582 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
2583 HandleScope scope;
2584 NeanderArray listeners(i::Factory::message_listeners());
2585 NeanderObject obj(2);
2586 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
2587 obj.set(1, data.IsEmpty() ?
2588 i::Heap::undefined_value() :
2589 *Utils::OpenHandle(*data));
2590 listeners.add(obj.value());
2591 return true;
2592}
2593
2594
2595void V8::RemoveMessageListeners(MessageCallback that) {
2596 EnsureInitialized("v8::V8::RemoveMessageListener()");
2597 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
2598 HandleScope scope;
2599 NeanderArray listeners(i::Factory::message_listeners());
2600 for (int i = 0; i < listeners.length(); i++) {
2601 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
2602
2603 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
2604 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
2605 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
2606 listeners.set(i, i::Heap::undefined_value());
2607 }
2608 }
2609}
2610
2611
2612void V8::SetCounterFunction(CounterLookupCallback callback) {
2613 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
2614 i::StatsTable::SetCounterFunction(callback);
2615}
2616
2617
2618void V8::EnableSlidingStateWindow() {
2619 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
2620 i::Logger::EnableSlidingStateWindow();
2621}
2622
2623
2624void V8::SetFailedAccessCheckCallbackFunction(
2625 FailedAccessCheckCallback callback) {
2626 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
2627 i::Top::SetFailedAccessCheckCallback(callback);
2628}
2629
2630
2631void V8::AddObjectToGroup(void* group_id, Persistent<Object> obj) {
2632 if (IsDeadCheck("v8::V8::AddObjectToGroup()")) return;
2633 i::GlobalHandles::AddToGroup(group_id, reinterpret_cast<i::Object**>(*obj));
2634}
2635
2636
kasper.lund7276f142008-07-30 08:49:36 +00002637int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
2638 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
2639 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
2640}
2641
2642
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002643void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
2644 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
2645 i::Heap::SetGlobalGCPrologueCallback(callback);
2646}
2647
2648
2649void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
2650 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
2651 i::Heap::SetGlobalGCEpilogueCallback(callback);
2652}
2653
2654
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002655void V8::SetExternalSymbolCallback(ExternalSymbolCallback callback) {
2656 if (IsDeadCheck("v8::V8::SetExternalSymbolCallback()")) return;
2657 i::Heap::SetExternalSymbolCallback(callback);
2658}
2659
2660
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002661String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
2662 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002663 if (obj.IsEmpty()) {
2664 str_ = NULL;
2665 length_ = 0;
2666 return;
2667 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002668 HandleScope scope;
2669 TryCatch try_catch;
2670 Handle<String> str = obj->ToString();
2671 if (str.IsEmpty()) {
2672 str_ = NULL;
2673 length_ = 0;
2674 } else {
2675 length_ = str->Utf8Length();
2676 str_ = i::NewArray<char>(length_ + 1);
2677 str->WriteUtf8(str_);
2678 }
2679}
2680
2681
2682String::Utf8Value::~Utf8Value() {
2683 i::DeleteArray(str_);
2684}
2685
2686
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002687String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
2688 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002689 if (obj.IsEmpty()) {
2690 str_ = NULL;
2691 length_ = 0;
2692 return;
2693 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002694 HandleScope scope;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002695 TryCatch try_catch;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002696 Handle<String> str = obj->ToString();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002697 if (str.IsEmpty()) {
2698 str_ = NULL;
2699 length_ = 0;
2700 } else {
2701 length_ = str->Length();
2702 str_ = i::NewArray<char>(length_ + 1);
2703 str->WriteAscii(str_);
2704 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002705}
2706
2707
2708String::AsciiValue::~AsciiValue() {
2709 i::DeleteArray(str_);
2710}
2711
2712
2713String::Value::Value(v8::Handle<v8::Value> obj) {
2714 EnsureInitialized("v8::String::Value::Value()");
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002715 if (obj.IsEmpty()) {
2716 str_ = NULL;
2717 length_ = 0;
2718 return;
2719 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002720 HandleScope scope;
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002721 TryCatch try_catch;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002722 Handle<String> str = obj->ToString();
ager@chromium.org9258b6b2008-09-11 09:11:10 +00002723 if (str.IsEmpty()) {
2724 str_ = NULL;
2725 length_ = 0;
2726 } else {
2727 length_ = str->Length();
2728 str_ = i::NewArray<uint16_t>(length_ + 1);
2729 str->Write(str_);
2730 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002731}
2732
2733
2734String::Value::~Value() {
2735 i::DeleteArray(str_);
2736}
2737
2738Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
2739 LOG_API("RangeError");
2740 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
2741 i::Object* error;
2742 {
2743 HandleScope scope;
2744 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
2745 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
2746 error = *result;
2747 }
2748 i::Handle<i::Object> result(error);
2749 return Utils::ToLocal(result);
2750}
2751
2752Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
2753 LOG_API("ReferenceError");
2754 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
2755 i::Object* error;
2756 {
2757 HandleScope scope;
2758 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
2759 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
2760 error = *result;
2761 }
2762 i::Handle<i::Object> result(error);
2763 return Utils::ToLocal(result);
2764}
2765
2766Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
2767 LOG_API("SyntaxError");
2768 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
2769 i::Object* error;
2770 {
2771 HandleScope scope;
2772 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
2773 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
2774 error = *result;
2775 }
2776 i::Handle<i::Object> result(error);
2777 return Utils::ToLocal(result);
2778}
2779
2780Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
2781 LOG_API("TypeError");
2782 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
2783 i::Object* error;
2784 {
2785 HandleScope scope;
2786 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
2787 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
2788 error = *result;
2789 }
2790 i::Handle<i::Object> result(error);
2791 return Utils::ToLocal(result);
2792}
2793
2794Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
2795 LOG_API("Error");
2796 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
2797 i::Object* error;
2798 {
2799 HandleScope scope;
2800 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
2801 i::Handle<i::Object> result = i::Factory::NewError(message);
2802 error = *result;
2803 }
2804 i::Handle<i::Object> result(error);
2805 return Utils::ToLocal(result);
2806}
2807
2808
2809// --- D e b u g S u p p o r t ---
2810
2811
2812bool Debug::AddDebugEventListener(DebugEventCallback that, Handle<Value> data) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002813 EnsureInitialized("v8::Debug::AddDebugEventListener()");
2814 ON_BAILOUT("v8::Debug::AddDebugEventListener()", return false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002815 HandleScope scope;
2816 NeanderArray listeners(i::Factory::debug_event_listeners());
2817 NeanderObject obj(2);
2818 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
2819 obj.set(1, data.IsEmpty() ?
2820 i::Heap::undefined_value() :
2821 *Utils::OpenHandle(*data));
2822 listeners.add(obj.value());
2823 i::Debugger::UpdateActiveDebugger();
2824 return true;
2825}
2826
2827
2828bool Debug::AddDebugEventListener(v8::Handle<v8::Function> that,
2829 Handle<Value> data) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002830 ON_BAILOUT("v8::Debug::AddDebugEventListener()", return false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002831 HandleScope scope;
2832 NeanderArray listeners(i::Factory::debug_event_listeners());
2833 NeanderObject obj(2);
2834 obj.set(0, *Utils::OpenHandle(*that));
2835 obj.set(1, data.IsEmpty() ?
2836 i::Heap::undefined_value() :
2837 *Utils::OpenHandle(*data));
2838 listeners.add(obj.value());
2839 i::Debugger::UpdateActiveDebugger();
2840 return true;
2841}
2842
2843
2844void Debug::RemoveDebugEventListener(DebugEventCallback that) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002845 EnsureInitialized("v8::Debug::RemoveDebugEventListener()");
2846 ON_BAILOUT("v8::Debug::RemoveDebugEventListener()", return);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002847 HandleScope scope;
2848 NeanderArray listeners(i::Factory::debug_event_listeners());
2849 for (int i = 0; i < listeners.length(); i++) {
2850 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
2851
2852 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
2853 // When removing a C debug event listener only consider proxy objects.
2854 if (listener.get(0)->IsProxy()) {
2855 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
2856 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
2857 listeners.set(i, i::Heap::undefined_value());
2858 }
2859 }
2860 }
2861 i::Debugger::UpdateActiveDebugger();
2862}
2863
2864
2865void Debug::RemoveDebugEventListener(v8::Handle<v8::Function> that) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002866 ON_BAILOUT("v8::Debug::RemoveDebugEventListener()", return);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002867 HandleScope scope;
2868 NeanderArray listeners(i::Factory::debug_event_listeners());
2869 for (int i = 0; i < listeners.length(); i++) {
2870 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
2871
2872 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
2873 // When removing a JavaScript debug event listener only consider JavaScript
2874 // function objects.
2875 if (listener.get(0)->IsJSFunction()) {
2876 i::JSFunction* callback = i::JSFunction::cast(listener.get(0));
2877 i::Handle<i::JSFunction> callback_fun(callback);
2878 if (callback_fun.is_identical_to(Utils::OpenHandle(*that))) {
2879 listeners.set(i, i::Heap::undefined_value());
2880 }
2881 }
2882 }
2883 i::Debugger::UpdateActiveDebugger();
2884}
2885
2886
2887void Debug::DebugBreak() {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002888 if (!i::V8::HasBeenSetup()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002889 i::StackGuard::DebugBreak();
2890}
2891
2892
2893void Debug::SetMessageHandler(v8::DebugMessageHandler handler, void* data) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002894 EnsureInitialized("v8::Debug::SetMessageHandler");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002895 i::Debugger::SetMessageHandler(handler, data);
2896}
2897
2898
2899void Debug::SendCommand(const uint16_t* command, int length) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00002900 if (!i::V8::HasBeenSetup()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002901 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length));
2902}
2903
2904
ager@chromium.orga74f0da2008-12-03 16:05:52 +00002905Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
2906 v8::Handle<v8::Value> data) {
2907 if (!i::V8::HasBeenSetup()) return Handle<Value>();
2908 ON_BAILOUT("v8::Debug::Call()", return Handle<Value>());
2909 i::Handle<i::Object> result;
2910 EXCEPTION_PREAMBLE();
2911 if (data.IsEmpty()) {
2912 result = i::Debugger::Call(Utils::OpenHandle(*fun),
2913 i::Factory::undefined_value(),
2914 &has_pending_exception);
2915 } else {
2916 result = i::Debugger::Call(Utils::OpenHandle(*fun),
2917 Utils::OpenHandle(*data),
2918 &has_pending_exception);
2919 }
2920 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2921 return Utils::ToLocal(result);
2922}
2923
2924
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002925namespace internal {
2926
2927
2928HandleScopeImplementer* HandleScopeImplementer::instance() {
2929 return &thread_local;
2930}
2931
2932
2933char* HandleScopeImplementer::ArchiveThread(char* storage) {
2934 return thread_local.ArchiveThreadHelper(storage);
2935}
2936
2937
2938char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
2939 ImplementationUtilities::HandleScopeData* current =
2940 ImplementationUtilities::CurrentHandleScope();
2941 handle_scope_data_ = *current;
2942 memcpy(storage, this, sizeof(*this));
2943
2944 Initialize();
2945 current->Initialize();
2946
2947 return storage + ArchiveSpacePerThread();
2948}
2949
2950
2951int HandleScopeImplementer::ArchiveSpacePerThread() {
2952 return sizeof(thread_local);
2953}
2954
2955
2956char* HandleScopeImplementer::RestoreThread(char* storage) {
2957 return thread_local.RestoreThreadHelper(storage);
2958}
2959
2960
2961char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
2962 memcpy(this, storage, sizeof(*this));
2963 *ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
2964 return storage + ArchiveSpacePerThread();
2965}
2966
2967
2968void HandleScopeImplementer::Iterate(
2969 ObjectVisitor* v,
2970 List<void**>* blocks,
2971 ImplementationUtilities::HandleScopeData* handle_data) {
2972 // Iterate over all handles in the blocks except for the last.
2973 for (int i = blocks->length() - 2; i >= 0; --i) {
2974 Object** block =
2975 reinterpret_cast<Object**>(blocks->at(i));
2976 v->VisitPointers(block, &block[kHandleBlockSize]);
2977 }
2978
2979 // Iterate over live handles in the last block (if any).
2980 if (!blocks->is_empty()) {
2981 v->VisitPointers(reinterpret_cast<Object**>(blocks->last()),
2982 reinterpret_cast<Object**>(handle_data->next));
2983 }
2984}
2985
2986
2987void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
2988 ImplementationUtilities::HandleScopeData* current =
2989 ImplementationUtilities::CurrentHandleScope();
2990 Iterate(v, thread_local.Blocks(), current);
2991}
2992
2993
2994char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
2995 HandleScopeImplementer* thread_local =
2996 reinterpret_cast<HandleScopeImplementer*>(storage);
2997 List<void**>* blocks_of_archived_thread = thread_local->Blocks();
2998 ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
2999 &thread_local->handle_scope_data_;
3000 Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread);
3001
3002 return storage + ArchiveSpacePerThread();
3003}
3004
3005} } // namespace v8::internal