blob: e16b1b24959d0ae9611732bd716971c695d06a8f [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001
2// Copyright 2006-2008 the V8 project authors. All rights reserved.
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are
5// met:
6//
7// * Redistributions of source code must retain the above copyright
8// notice, this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above
10// copyright notice, this list of conditions and the following
11// disclaimer in the documentation and/or other materials provided
12// with the distribution.
13// * Neither the name of Google Inc. nor the names of its
14// contributors may be used to endorse or promote products derived
15// from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "v8.h"
30
31#include "api.h"
32#include "execution.h"
33#include "spaces-inl.h"
34#include "top.h"
35
36namespace v8 {
37namespace internal {
38
39
40// If no message listeners have been registered this one is called
41// by default.
42void MessageHandler::DefaultMessageReport(const MessageLocation* loc,
43 Handle<Object> message_obj) {
44 SmartPointer<char> str = GetLocalizedMessage(message_obj);
45 if (loc == NULL) {
46 PrintF("%s\n", *str);
47 } else {
48 HandleScope scope;
49 Handle<Object> data(loc->script()->name());
50 SmartPointer<char> data_str;
51 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
59void MessageHandler::ReportMessage(const char* msg) {
60 PrintF("%s\n", msg);
61}
62
63
64Handle<Object> MessageHandler::MakeMessageObject(
65 const char* type,
66 MessageLocation* loc,
67 Vector< Handle<Object> > args,
68 Handle<String> stack_trace) {
69 // Build error message object
70 v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
71 Handle<Object> type_str = Factory::LookupAsciiSymbol(type);
72 Handle<Object> array = Factory::NewJSArray(args.length());
73 for (int i = 0; i < args.length(); i++)
74 SetElement(Handle<JSArray>::cast(array), i, args[i]);
75
76 Handle<JSFunction> fun(Top::global_context()->make_message_fun());
77 int start, end;
78 Handle<Object> script;
79 if (loc) {
80 start = loc->start_pos();
81 end = loc->end_pos();
82 script = GetScriptWrapper(loc->script());
83 } else {
84 start = end = 0;
85 script = Factory::undefined_value();
86 }
87 Handle<Object> start_handle(Smi::FromInt(start));
88 Handle<Object> end_handle(Smi::FromInt(end));
89 Handle<Object> stack_trace_val = stack_trace.is_null()
90 ? Factory::undefined_value()
91 : Handle<Object>::cast(stack_trace);
92 const int argc = 6;
93 Object** argv[argc] = { type_str.location(),
94 array.location(),
95 start_handle.location(),
96 end_handle.location(),
97 script.location(),
98 stack_trace_val.location() };
99
100 // Setup a catch handler to catch exceptions in creating the message. This
101 // handler is non-verbose to avoid calling MakeMessage recursively in case of
102 // an exception.
103 v8::TryCatch catcher;
104 catcher.SetVerbose(false);
105 catcher.SetCaptureMessage(false);
106
107 // Format the message.
108 bool caught_exception = false;
109 Handle<Object> message =
110 Execution::Call(fun, Factory::undefined_value(), argc, argv,
111 &caught_exception);
112
113 // If creating the message (in JS code) resulted in an exception, we
114 // skip doing the callback. This usually only happens in case of
115 // stack overflow exceptions being thrown by the parser when the
116 // stack is almost full.
117 if (caught_exception) return Handle<Object>();
118
119 return message.EscapeFrom(&scope);
120}
121
122
123void MessageHandler::ReportMessage(MessageLocation* loc,
124 Handle<Object> message) {
125 v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
126
127 v8::NeanderArray global_listeners(Factory::message_listeners());
128 int global_length = global_listeners.length();
129 if (global_length == 0) {
130 DefaultMessageReport(loc, message);
131 } else {
132 for (int i = 0; i < global_length; i++) {
133 HandleScope scope;
134 if (global_listeners.get(i)->IsUndefined()) continue;
135 v8::NeanderObject listener(JSObject::cast(global_listeners.get(i)));
136 Handle<Proxy> callback_obj(Proxy::cast(listener.get(0)));
137 v8::MessageCallback callback =
138 FUNCTION_CAST<v8::MessageCallback>(callback_obj->proxy());
139 Handle<Object> callback_data(listener.get(1));
140 callback(api_message_obj, v8::Utils::ToLocal(callback_data));
141 }
142 }
143}
144
145
146Handle<String> MessageHandler::GetMessage(Handle<Object> data) {
147 Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage");
148 Handle<JSFunction> fun =
149 Handle<JSFunction>(
150 JSFunction::cast(Top::builtins()->GetProperty(*fmt_str)));
151 Object** argv[1] = { data.location() };
152
153 bool caught_exception;
154 Handle<Object> result =
155 Execution::TryCall(fun, Top::builtins(), 1, argv, &caught_exception);
156
157 if (caught_exception || !result->IsString()) {
158 return Factory::LookupAsciiSymbol("<error>");
159 }
160 Handle<String> result_string = Handle<String>::cast(result);
161 // A string that has been obtained from JS code in this way is
162 // likely to be a complicated ConsString of some sort. We flatten it
163 // here to improve the efficiency of converting it to a C string and
164 // other operations that are likely to take place (see GetLocalizedMessage
165 // for example).
166 FlattenString(result_string);
167 return result_string;
168}
169
170
171SmartPointer<char> MessageHandler::GetLocalizedMessage(Handle<Object> data) {
172 HandleScope scope;
173 return GetMessage(data)->ToCString(DISALLOW_NULLS);
174}
175
176
177} } // namespace v8::internal