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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "bindings/core/v8/ScriptFunctionCall.h"
     33 
     34 #include "bindings/core/v8/ScriptController.h"
     35 #include "bindings/core/v8/ScriptState.h"
     36 #include "bindings/core/v8/ScriptValue.h"
     37 #include "bindings/core/v8/V8Binding.h"
     38 #include "bindings/core/v8/V8ObjectConstructor.h"
     39 #include "bindings/core/v8/V8ScriptRunner.h"
     40 
     41 #include <v8.h>
     42 
     43 namespace blink {
     44 
     45 void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument)
     46 {
     47     if (argument.scriptState() != m_scriptState) {
     48         appendUndefinedArgument();
     49         return;
     50     }
     51     m_arguments.append(argument);
     52 }
     53 
     54 void ScriptCallArgumentHandler::appendArgument(const String& argument)
     55 {
     56     v8::Isolate* isolate = m_scriptState->isolate();
     57     ScriptState::Scope scope(m_scriptState.get());
     58     m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument)));
     59 }
     60 
     61 void ScriptCallArgumentHandler::appendArgument(const char* argument)
     62 {
     63     v8::Isolate* isolate = m_scriptState->isolate();
     64     ScriptState::Scope scope(m_scriptState.get());
     65     m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument)));
     66 }
     67 
     68 void ScriptCallArgumentHandler::appendArgument(long argument)
     69 {
     70     v8::Isolate* isolate = m_scriptState->isolate();
     71     ScriptState::Scope scope(m_scriptState.get());
     72     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument)));
     73 }
     74 
     75 void ScriptCallArgumentHandler::appendArgument(long long argument)
     76 {
     77     v8::Isolate* isolate = m_scriptState->isolate();
     78     ScriptState::Scope scope(m_scriptState.get());
     79     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument)));
     80 }
     81 
     82 void ScriptCallArgumentHandler::appendArgument(unsigned argument)
     83 {
     84     v8::Isolate* isolate = m_scriptState->isolate();
     85     ScriptState::Scope scope(m_scriptState.get());
     86     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument)));
     87 }
     88 
     89 void ScriptCallArgumentHandler::appendArgument(unsigned long argument)
     90 {
     91     v8::Isolate* isolate = m_scriptState->isolate();
     92     ScriptState::Scope scope(m_scriptState.get());
     93     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument)));
     94 }
     95 
     96 void ScriptCallArgumentHandler::appendArgument(int argument)
     97 {
     98     v8::Isolate* isolate = m_scriptState->isolate();
     99     ScriptState::Scope scope(m_scriptState.get());
    100     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument)));
    101 }
    102 
    103 void ScriptCallArgumentHandler::appendArgument(bool argument)
    104 {
    105     v8::Isolate* isolate = m_scriptState->isolate();
    106     m_arguments.append(ScriptValue(m_scriptState.get(), v8Boolean(argument, isolate)));
    107 }
    108 
    109 void ScriptCallArgumentHandler::appendArgument(const Vector<ScriptValue>& argument)
    110 {
    111     v8::Isolate* isolate = m_scriptState->isolate();
    112     ScriptState::Scope scope(m_scriptState.get());
    113     v8::Handle<v8::Array> result = v8::Array::New(isolate, argument.size());
    114     for (size_t i = 0; i < argument.size(); ++i) {
    115         if (argument[i].scriptState() != m_scriptState)
    116             result->Set(v8::Integer::New(isolate, i), v8::Undefined(isolate));
    117         else
    118             result->Set(v8::Integer::New(isolate, i), argument[i].v8Value());
    119     }
    120     m_arguments.append(ScriptValue(m_scriptState.get(), result));
    121 }
    122 
    123 void ScriptCallArgumentHandler::appendUndefinedArgument()
    124 {
    125     v8::Isolate* isolate = m_scriptState->isolate();
    126     m_arguments.append(ScriptValue(m_scriptState.get(), v8::Undefined(isolate)));
    127 }
    128 
    129 ScriptFunctionCall::ScriptFunctionCall(const ScriptValue& thisObject, const String& name)
    130     : ScriptCallArgumentHandler(thisObject.scriptState())
    131     , m_thisObject(thisObject)
    132     , m_name(name)
    133 {
    134 }
    135 
    136 ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions)
    137 {
    138     ScriptState::Scope scope(m_scriptState.get());
    139     v8::TryCatch tryCatch;
    140     tryCatch.SetVerbose(reportExceptions);
    141 
    142     v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value());
    143     v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name));
    144     if (tryCatch.HasCaught()) {
    145         hadException = true;
    146         return ScriptValue();
    147     }
    148 
    149     ASSERT(value->IsFunction());
    150 
    151     v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
    152     OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[m_arguments.size()]);
    153     for (size_t i = 0; i < m_arguments.size(); ++i) {
    154         info[i] = m_arguments[i].v8Value();
    155         ASSERT(!info[i].IsEmpty());
    156     }
    157 
    158     v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, m_scriptState->executionContext(), thisObject, m_arguments.size(), info.get(), m_scriptState->isolate());
    159     if (tryCatch.HasCaught()) {
    160         hadException = true;
    161         return ScriptValue();
    162     }
    163 
    164     return ScriptValue(m_scriptState.get(), result);
    165 }
    166 
    167 ScriptValue ScriptFunctionCall::call()
    168 {
    169     bool hadException = false;
    170     return call(hadException);
    171 }
    172 
    173 ScriptValue ScriptFunctionCall::construct(bool& hadException, bool reportExceptions)
    174 {
    175     ScriptState::Scope scope(m_scriptState.get());
    176     v8::TryCatch tryCatch;
    177     tryCatch.SetVerbose(reportExceptions);
    178 
    179     v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value());
    180     v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name));
    181     if (tryCatch.HasCaught()) {
    182         hadException = true;
    183         return ScriptValue();
    184     }
    185 
    186     ASSERT(value->IsFunction());
    187 
    188     v8::Local<v8::Function> constructor = v8::Local<v8::Function>::Cast(value);
    189     OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[m_arguments.size()]);
    190     for (size_t i = 0; i < m_arguments.size(); ++i)
    191         info[i] = m_arguments[i].v8Value();
    192 
    193     v8::Local<v8::Object> result = V8ObjectConstructor::newInstance(m_scriptState->isolate(), constructor, m_arguments.size(), info.get());
    194     if (tryCatch.HasCaught()) {
    195         hadException = true;
    196         return ScriptValue();
    197     }
    198 
    199     return ScriptValue(m_scriptState.get(), result);
    200 }
    201 
    202 } // namespace blink
    203