Add a JSScriptRef API to JSC so that we can allow API users to avoid the full cost...
[WebKit-https.git] / Source / JavaScriptCore / API / JSScriptRef.cpp
1 /*
2  * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "APICast.h"
29 #include "APIShims.h"
30 #include "Completion.h"
31 #include "JSBasePrivate.h"
32 #include "JSGlobalData.h"
33 #include "JSScriptRefPrivate.h"
34 #include "OpaqueJSString.h"
35 #include "SourceCode.h"
36 #include "SourceProvider.h"
37
38 using namespace JSC;
39
40 struct OpaqueJSScript : public SourceProvider {
41 public:
42     static WTF::PassRefPtr<OpaqueJSScript> create(JSGlobalData* globalData, const String& url, int startingLineNumber, const String& source)
43     {
44         return WTF::adoptRef(new OpaqueJSScript(globalData, url, startingLineNumber, source));
45     }
46
47     const String& source() const OVERRIDE
48     {
49         return m_source;
50     }
51
52     const JSGlobalData* globalData() const { return m_globalData; }
53
54 private:
55     OpaqueJSScript(JSGlobalData* globalData, const String& url, int startingLineNumber, const String& source)
56         : SourceProvider(url, TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()))
57         , m_globalData(globalData)
58         , m_source(source)
59     {
60     }
61
62     ~OpaqueJSScript() { }
63
64     JSGlobalData* m_globalData;
65     String m_source;
66 };
67
68 extern "C" {
69
70 JSScriptRef JSScriptCreateReferencingImmortalASCIIText(JSContextRef context, JSStringRef url, int startingLineNumber, const char* source, size_t length, JSValueRef* exception)
71 {
72     ExecState* exec = toJS(context);
73     APIEntryShim entryShim(exec);
74     JSGlobalData* globalData = &exec->globalData();
75     for (size_t i = 0; i < length; i++) {
76         if (!isASCII(source[i]))
77             return 0;
78     }
79
80     RefPtr<OpaqueJSScript> result = OpaqueJSScript::create(globalData, url->string(), startingLineNumber, String(StringImpl::createFromLiteral(source, length)));
81     JSValue exceptionValue;
82     if (!checkSyntax(exec, SourceCode(result), &exceptionValue)) {
83         if (exception)
84             *exception = toRef(exec, exceptionValue);
85         return 0;
86     }
87
88     return result.release().leakRef();
89 }
90
91 JSScriptRef JSScriptCreateFromString(JSContextRef context, JSStringRef url, int startingLineNumber, JSStringRef source, JSValueRef* exception)
92 {
93     ExecState* exec = toJS(context);
94     APIEntryShim entryShim(exec);
95     JSGlobalData* globalData = &exec->globalData();
96
97     RefPtr<OpaqueJSScript> result = OpaqueJSScript::create(globalData, url->string(), startingLineNumber, source->string());
98     JSValue exceptionValue;
99     if (!checkSyntax(exec, SourceCode(result), &exceptionValue)) {
100         if (exception)
101             *exception = toRef(exec, exceptionValue);
102         return 0;
103     }
104     return result.release().leakRef();
105 }
106
107 void JSScriptRetain(JSContextRef context, JSScriptRef script)
108 {
109     ExecState* exec = toJS(context);
110     APIEntryShim entryShim(exec);
111     if (script->globalData() != &exec->globalData())
112         CRASH();
113     script->ref();
114 }
115
116 void JSScriptRelease(JSContextRef context, JSScriptRef script)
117 {
118     ExecState* exec = toJS(context);
119     APIEntryShim entryShim(exec);
120     if (script->globalData() != &exec->globalData())
121         CRASH();
122     script->deref();
123 }
124
125 JSValueRef JSScriptEvaluate(JSContextRef context, JSScriptRef script, JSValueRef thisValueRef, JSValueRef* exception)
126 {
127     ExecState* exec = toJS(context);
128     APIEntryShim entryShim(exec);
129     if (script->globalData() != &exec->globalData()) {
130         ASSERT_NOT_REACHED();
131         return 0;
132     }
133     JSValue internalException;
134     JSValue thisValue = thisValueRef ? toJS(exec, thisValueRef) : jsUndefined();
135     JSValue result = evaluate(exec, SourceCode(script), thisValue, &internalException);
136     if (internalException) {
137         if (exception)
138             *exception = toRef(exec, internalException);
139         return 0;
140     }
141     ASSERT(result);
142     return toRef(exec, result);
143 }
144
145 }