Adds a JavaScriptCallFrame object and JavaScript binding with an IDL.
[WebKit-https.git] / WebCore / page / JavaScriptCallFrame.cpp
1 /*
2  * Copyright (C) 2008 Apple 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JavaScriptCallFrame.h"
28
29 #include "PlatformString.h"
30 #include <kjs/JSGlobalObject.h>
31 #include <kjs/interpreter.h>
32 #include <kjs/object.h>
33 #include <kjs/value.h>
34
35 using namespace KJS;
36
37 namespace WebCore {
38
39 JavaScriptCallFrame::JavaScriptCallFrame(ExecState* exec, PassRefPtr<JavaScriptCallFrame> caller, int sourceID, int line)
40     : m_exec(exec)
41     , m_caller(caller)
42     , m_sourceID(sourceID)
43     , m_line(line)
44 {
45 }
46
47 JavaScriptCallFrame* JavaScriptCallFrame::caller()
48 {
49     return m_caller.get();
50 }
51
52 String JavaScriptCallFrame::functionName() const
53 {
54     if (!m_exec || !m_exec->scopeNode())
55         return String();
56
57     FunctionImp* function = m_exec->function();
58     if (!function)
59         return String();
60
61     return String(function->functionName());
62 }
63
64 // Evaluate some JavaScript code in the context of this frame.
65 // The code is evaluated as if by "eval", and the result is returned.
66 // If there is an (uncaught) exception, it is returned as though _it_ were the result.
67
68 // FIXME: If "script" contains var declarations, the machinery to handle local variables
69 // efficiently in JavaScriptCore will not work properly. This could lead to crashes or
70 // incorrect variable values. So this is not appropriate for evaluating arbitrary scripts.
71
72 JSValue* JavaScriptCallFrame::evaluate(const UString& script) const
73 {
74     if (!m_exec)
75         return jsNull();
76
77     JSLock lock;
78
79     ExecState* exec = m_exec;
80     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
81
82     // find "eval"
83     JSObject* eval = 0;
84     if (exec->scopeNode()) {  // "eval" won't work without context (i.e. at global scope)
85         JSValue* v = globalObject->get(exec, "eval");
86         if (v->isObject() && static_cast<JSObject*>(v)->implementsCall())
87             eval = static_cast<JSObject*>(v);
88         else
89             // no "eval" - fallback operates on global exec state
90             exec = globalObject->globalExec();
91     }
92
93     JSValue* savedException = exec->exception();
94     exec->clearException();
95
96     // evaluate
97     JSValue* result = 0;
98     if (eval) {
99         List args;
100         args.append(jsString(script));
101         result = eval->call(exec, 0, args);
102     } else
103         // no "eval", or no context (i.e. global scope) - use global fallback
104         result = Interpreter::evaluate(exec, UString(), 0, script.data(), script.size(), globalObject).value();
105
106     if (exec->hadException())
107         result = exec->exception();    // (may be redundant depending on which eval path was used)
108     exec->setException(savedException);
109
110     return result;
111 }
112
113 } // namespace WebCore