Home | History | Annotate | Download | only in v8
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1.  Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  * 2.  Redistributions in binary form must reproduce the above copyright
     10  *     notice, this list of conditions and the following disclaimer in the
     11  *     documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 #include "bindings/v8/V8ThrowException.h"
     27 
     28 #include "V8DOMException.h"
     29 #include "bindings/v8/V8Binding.h"
     30 #include "core/dom/DOMException.h"
     31 #include "core/dom/ExceptionCode.h"
     32 
     33 namespace WebCore {
     34 
     35 static void domExceptionStackGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
     36 {
     37     ASSERT(info.Data()->IsObject());
     38     v8SetReturnValue(info, info.Data()->ToObject()->Get(v8AtomicString(info.GetIsolate(), "stack")));
     39 }
     40 
     41 static void domExceptionStackSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
     42 {
     43     ASSERT(info.Data()->IsObject());
     44     info.Data()->ToObject()->Set(v8AtomicString(info.GetIsolate(), "stack"), value);
     45 }
     46 
     47 v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate)
     48 {
     49     if (ec <= 0 || v8::V8::IsExecutionTerminating())
     50         return v8Undefined();
     51 
     52     ASSERT(ec == SecurityError || unsanitizedMessage.isEmpty());
     53 
     54     // FIXME: Handle other WebIDL exception types.
     55     if (ec == TypeError)
     56         return V8ThrowException::createTypeError(sanitizedMessage, isolate);
     57 
     58     RefPtr<DOMException> domException = DOMException::create(ec, sanitizedMessage, unsanitizedMessage);
     59     v8::Handle<v8::Value> exception = toV8(domException, creationContext, isolate);
     60 
     61     if (exception.IsEmpty())
     62         return v8Undefined();
     63 
     64     // Attach an Error object to the DOMException. This is then lazily used to get the stack value.
     65     v8::Handle<v8::Value> error = v8::Exception::Error(v8String(isolate, domException->message()));
     66     ASSERT(!error.IsEmpty());
     67     ASSERT(exception->IsObject());
     68     exception->ToObject()->SetAccessor(v8AtomicString(isolate, "stack"), domExceptionStackGetter, domExceptionStackSetter, error);
     69 
     70     return exception;
     71 }
     72 
     73 v8::Handle<v8::Value> V8ThrowException::throwDOMException(int ec, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate)
     74 {
     75     ASSERT(ec == SecurityError || unsanitizedMessage.isEmpty());
     76     v8::Handle<v8::Value> exception = createDOMException(ec, sanitizedMessage, unsanitizedMessage, creationContext, isolate);
     77     if (exception.IsEmpty())
     78         return v8Undefined();
     79 
     80     return V8ThrowException::throwError(exception, isolate);
     81 }
     82 
     83 v8::Handle<v8::Value> V8ThrowException::createError(V8ErrorType type, const String& message, v8::Isolate* isolate)
     84 {
     85     switch (type) {
     86     case v8RangeError:
     87         return v8::Exception::RangeError(v8String(isolate, message));
     88     case v8ReferenceError:
     89         return v8::Exception::ReferenceError(v8String(isolate, message));
     90     case v8SyntaxError:
     91         return v8::Exception::SyntaxError(v8String(isolate, message));
     92     case v8TypeError:
     93         return v8::Exception::TypeError(v8String(isolate, message));
     94     case v8GeneralError:
     95         return v8::Exception::Error(v8String(isolate, message));
     96     default:
     97         ASSERT_NOT_REACHED();
     98         return v8Undefined();
     99     }
    100 }
    101 
    102 v8::Handle<v8::Value> V8ThrowException::throwError(V8ErrorType type, const String& message, v8::Isolate* isolate)
    103 {
    104     v8::Handle<v8::Value> exception = V8ThrowException::createError(type, message, isolate);
    105     if (exception.IsEmpty())
    106         return v8Undefined();
    107     return V8ThrowException::throwError(exception, isolate);
    108 }
    109 
    110 v8::Handle<v8::Value> V8ThrowException::createTypeError(const String& message, v8::Isolate* isolate)
    111 {
    112     return v8::Exception::TypeError(v8String(isolate, message.isNull() ? "Type error" : message));
    113 }
    114 
    115 v8::Handle<v8::Value> V8ThrowException::throwTypeError(const String& message, v8::Isolate* isolate)
    116 {
    117     v8::Handle<v8::Value> exception = V8ThrowException::createTypeError(message, isolate);
    118     return V8ThrowException::throwError(exception, isolate);
    119 }
    120 
    121 v8::Handle<v8::Value> V8ThrowException::throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate)
    122 {
    123     if (!v8::V8::IsExecutionTerminating())
    124         isolate->ThrowException(exception);
    125     return v8::Undefined(isolate);
    126 }
    127 
    128 } // namespace WebCore
    129