blob: 9eae67a72803302ef8333d94f3cd5fe01f3eda36 [file] [log] [blame]
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +00001// Copyright 2011 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 "execution.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000032#include "messages.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "spaces-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
kasperl@chromium.org71affb52009-05-26 05:44:31 +000035namespace v8 {
36namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38
39// If no message listeners have been registered this one is called
40// by default.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000041void MessageHandler::DefaultMessageReport(Isolate* isolate,
42 const MessageLocation* loc,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043 Handle<Object> message_obj) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000044 SmartArrayPointer<char> str = GetLocalizedMessage(isolate, message_obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045 if (loc == NULL) {
46 PrintF("%s\n", *str);
47 } else {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000048 HandleScope scope(isolate);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000049 Handle<Object> data(loc->script()->name(), isolate);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000050 SmartArrayPointer<char> data_str;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051 if (data->IsString())
52 data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS);
53 PrintF("%s:%i: %s\n", *data_str ? *data_str : "<unknown>",
54 loc->start_pos(), *str);
55 }
56}
57
58
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000059Handle<JSMessageObject> MessageHandler::MakeMessageObject(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000060 Isolate* isolate,
ager@chromium.org9258b6b2008-09-11 09:11:10 +000061 const char* type,
62 MessageLocation* loc,
63 Vector< Handle<Object> > args,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000064 Handle<String> stack_trace,
65 Handle<JSArray> stack_frames) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000066 Factory* factory = isolate->factory();
67 Handle<String> type_handle = factory->InternalizeUtf8String(type);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000068 Handle<FixedArray> arguments_elements =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000069 factory->NewFixedArray(args.length());
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000070 for (int i = 0; i < args.length(); i++) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000071 arguments_elements->set(i, *args[i]);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000072 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000073 Handle<JSArray> arguments_handle =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000074 factory->NewJSArrayWithElements(arguments_elements);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000076 int start = 0;
77 int end = 0;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000078 Handle<Object> script_handle = factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000079 if (loc) {
80 start = loc->start_pos();
81 end = loc->end_pos();
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000082 script_handle = GetScriptWrapper(loc->script());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000083 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000085 Handle<Object> stack_trace_handle = stack_trace.is_null()
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000086 ? Handle<Object>::cast(factory->undefined_value())
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000087 : Handle<Object>::cast(stack_trace);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000088
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000089 Handle<Object> stack_frames_handle = stack_frames.is_null()
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000090 ? Handle<Object>::cast(factory->undefined_value())
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000091 : Handle<Object>::cast(stack_frames);
ager@chromium.org3bf7b912008-11-17 09:09:45 +000092
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000093 Handle<JSMessageObject> message =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000094 factory->NewJSMessageObject(type_handle,
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000095 arguments_handle,
96 start,
97 end,
98 script_handle,
99 stack_trace_handle,
100 stack_frames_handle);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000101
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000102 return message;
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000103}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000105
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000106void MessageHandler::ReportMessage(Isolate* isolate,
107 MessageLocation* loc,
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000108 Handle<Object> message) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000109 // We are calling into embedder's code which can throw exceptions.
110 // Thus we need to save current exception state, reset it to the clean one
111 // and ignore scheduled exceptions callbacks can throw.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000112
113 // We pass the exception object into the message handler callback though.
114 Object* exception_object = isolate->heap()->undefined_value();
115 if (isolate->has_pending_exception()) {
116 isolate->pending_exception()->ToObject(&exception_object);
117 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000118 Handle<Object> exception_handle(exception_object, isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000119
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000120 Isolate::ExceptionScope exception_scope(isolate);
121 isolate->clear_pending_exception();
122 isolate->set_external_caught_exception(false);
123
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124 v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000125 v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception_handle);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000127 v8::NeanderArray global_listeners(isolate->factory()->message_listeners());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 int global_length = global_listeners.length();
129 if (global_length == 0) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000130 DefaultMessageReport(isolate, loc, message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000131 if (isolate->has_scheduled_exception()) {
132 isolate->clear_scheduled_exception();
133 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000134 } else {
135 for (int i = 0; i < global_length; i++) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000136 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137 if (global_listeners.get(i)->IsUndefined()) continue;
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000138 v8::NeanderObject listener(JSObject::cast(global_listeners.get(i)));
139 Handle<Foreign> callback_obj(Foreign::cast(listener.get(0)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140 v8::MessageCallback callback =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000141 FUNCTION_CAST<v8::MessageCallback>(callback_obj->foreign_address());
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000142 Handle<Object> callback_data(listener.get(1), isolate);
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000143 {
144 // Do not allow exceptions to propagate.
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000145 v8::TryCatch try_catch;
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000146 callback(api_message_obj, callback_data->IsUndefined()
147 ? api_exception_obj
148 : v8::Utils::ToLocal(callback_data));
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000149 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000150 if (isolate->has_scheduled_exception()) {
151 isolate->clear_scheduled_exception();
152 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153 }
154 }
155}
156
157
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000158Handle<String> MessageHandler::GetMessage(Isolate* isolate,
159 Handle<Object> data) {
160 Factory* factory = isolate->factory();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000161 Handle<String> fmt_str =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000162 factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("FormatMessage"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163 Handle<JSFunction> fun =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000164 Handle<JSFunction>(
165 JSFunction::cast(
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000166 isolate->js_builtins_object()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000167 GetPropertyNoExceptionThrown(*fmt_str)));
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000168 Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000169 Handle<Object> argv[] = { Handle<Object>(message->type(), isolate),
170 Handle<Object>(message->arguments(), isolate) };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000171
172 bool caught_exception;
173 Handle<Object> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000174 Execution::TryCall(fun,
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000175 isolate->js_builtins_object(),
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000176 ARRAY_SIZE(argv),
177 argv,
178 &caught_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000179
180 if (caught_exception || !result->IsString()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000181 return factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("<error>"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 }
183 Handle<String> result_string = Handle<String>::cast(result);
184 // A string that has been obtained from JS code in this way is
185 // likely to be a complicated ConsString of some sort. We flatten it
186 // here to improve the efficiency of converting it to a C string and
187 // other operations that are likely to take place (see GetLocalizedMessage
188 // for example).
189 FlattenString(result_string);
190 return result_string;
191}
192
193
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000194SmartArrayPointer<char> MessageHandler::GetLocalizedMessage(
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000195 Isolate* isolate,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000196 Handle<Object> data) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000197 HandleScope scope(isolate);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000198 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199}
200
201
202} } // namespace v8::internal