Home | History | Annotate | Download | only in src
      1 
      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 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 
     40 // If no message listeners have been registered this one is called
     41 // by default.
     42 void 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 
     59 void MessageHandler::ReportMessage(const char* msg) {
     60   PrintF("%s\n", msg);
     61 }
     62 
     63 
     64 Handle<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 
    123 void 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 
    146 Handle<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 
    171 SmartPointer<char> MessageHandler::GetLocalizedMessage(Handle<Object> data) {
    172   HandleScope scope;
    173   return GetMessage(data)->ToCString(DISALLOW_NULLS);
    174 }
    175 
    176 
    177 } }  // namespace v8::internal
    178