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 "VM.h" 33#include "JSScriptRefPrivate.h" 34#include "OpaqueJSString.h" 35#include "Operations.h" 36#include "Parser.h" 37#include "SourceCode.h" 38#include "SourceProvider.h" 39 40using namespace JSC; 41 42struct OpaqueJSScript : public SourceProvider { 43public: 44 static WTF::PassRefPtr<OpaqueJSScript> create(VM* vm, const String& url, int startingLineNumber, const String& source) 45 { 46 return WTF::adoptRef(new OpaqueJSScript(vm, url, startingLineNumber, source)); 47 } 48 49 const String& source() const OVERRIDE 50 { 51 return m_source; 52 } 53 54 VM* vm() const { return m_vm; } 55 56private: 57 OpaqueJSScript(VM* vm, const String& url, int startingLineNumber, const String& source) 58 : SourceProvider(url, TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first())) 59 , m_vm(vm) 60 , m_source(source) 61 { 62 } 63 64 ~OpaqueJSScript() { } 65 66 VM* m_vm; 67 String m_source; 68}; 69 70static bool parseScript(VM* vm, const SourceCode& source, ParserError& error) 71{ 72 return JSC::parse<JSC::ProgramNode>(vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); 73} 74 75extern "C" { 76 77JSScriptRef JSScriptCreateReferencingImmortalASCIIText(JSContextGroupRef contextGroup, JSStringRef url, int startingLineNumber, const char* source, size_t length, JSStringRef* errorMessage, int* errorLine) 78{ 79 VM* vm = toJS(contextGroup); 80 APIEntryShim entryShim(vm); 81 for (size_t i = 0; i < length; i++) { 82 if (!isASCII(source[i])) 83 return 0; 84 } 85 86 RefPtr<OpaqueJSScript> result = OpaqueJSScript::create(vm, url->string(), startingLineNumber, String(StringImpl::createFromLiteral(source, length))); 87 88 ParserError error; 89 if (!parseScript(vm, SourceCode(result), error)) { 90 if (errorMessage) 91 *errorMessage = OpaqueJSString::create(error.m_message).leakRef(); 92 if (errorLine) 93 *errorLine = error.m_line; 94 return 0; 95 } 96 97 return result.release().leakRef(); 98} 99 100JSScriptRef JSScriptCreateFromString(JSContextGroupRef contextGroup, JSStringRef url, int startingLineNumber, JSStringRef source, JSStringRef* errorMessage, int* errorLine) 101{ 102 VM* vm = toJS(contextGroup); 103 APIEntryShim entryShim(vm); 104 105 RefPtr<OpaqueJSScript> result = OpaqueJSScript::create(vm, url->string(), startingLineNumber, source->string()); 106 107 ParserError error; 108 if (!parseScript(vm, SourceCode(result), error)) { 109 if (errorMessage) 110 *errorMessage = OpaqueJSString::create(error.m_message).leakRef(); 111 if (errorLine) 112 *errorLine = error.m_line; 113 return 0; 114 } 115 116 return result.release().leakRef(); 117} 118 119void JSScriptRetain(JSScriptRef script) 120{ 121 APIEntryShim entryShim(script->vm()); 122 script->ref(); 123} 124 125void JSScriptRelease(JSScriptRef script) 126{ 127 APIEntryShim entryShim(script->vm()); 128 script->deref(); 129} 130 131JSValueRef JSScriptEvaluate(JSContextRef context, JSScriptRef script, JSValueRef thisValueRef, JSValueRef* exception) 132{ 133 ExecState* exec = toJS(context); 134 APIEntryShim entryShim(exec); 135 if (script->vm() != &exec->vm()) { 136 RELEASE_ASSERT_NOT_REACHED(); 137 return 0; 138 } 139 JSValue internalException; 140 JSValue thisValue = thisValueRef ? toJS(exec, thisValueRef) : jsUndefined(); 141 JSValue result = evaluate(exec, SourceCode(script), thisValue, &internalException); 142 if (internalException) { 143 if (exception) 144 *exception = toRef(exec, internalException); 145 return 0; 146 } 147 ASSERT(result); 148 return toRef(exec, result); 149} 150 151} 152