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'' 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#include "bindings/v8/V8ScriptRunner.h" 28 29#include "bindings/v8/V8Binding.h" 30#include "bindings/v8/V8GCController.h" 31#include "bindings/v8/V8RecursionScope.h" 32#include "core/dom/ScriptExecutionContext.h" 33#include "core/loader/CachedMetadata.h" 34#include "core/loader/cache/ScriptResource.h" 35#include "core/platform/chromium/TraceEvent.h" 36 37namespace WebCore { 38 39PassOwnPtr<v8::ScriptData> V8ScriptRunner::precompileScript(v8::Handle<v8::String> code, ScriptResource* resource) 40{ 41 TRACE_EVENT0("v8", "v8.compile"); 42 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); 43 // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from 44 // the ScriptResource. If the format changes, this ID should be changed too. 45 static const unsigned dataTypeID = 0xECC13BD7; 46 47 // Very small scripts are not worth the effort to preparse. 48 static const int minPreparseLength = 1024; 49 50 if (!resource || code->Length() < minPreparseLength) 51 return nullptr; 52 53 CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); 54 if (cachedMetadata) 55 return adoptPtr(v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size())); 56 57 OwnPtr<v8::ScriptData> scriptData = adoptPtr(v8::ScriptData::PreCompile(code)); 58 if (!scriptData) 59 return nullptr; 60 61 resource->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length()); 62 63 return scriptData.release(); 64} 65 66v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData, v8::Isolate* isolate, AccessControlStatus corsStatus) 67{ 68 TRACE_EVENT0("v8", "v8.compile"); 69 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); 70 v8::Handle<v8::String> name = v8String(fileName, isolate); 71 v8::Handle<v8::Integer> line = v8::Integer::New(scriptStartPosition.m_line.zeroBasedInt(), isolate); 72 v8::Handle<v8::Integer> column = v8::Integer::New(scriptStartPosition.m_column.zeroBasedInt(), isolate); 73 v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOrigin ? v8::True() : v8::False(); 74 v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); 75 return v8::Script::Compile(code, &origin, scriptData); 76} 77 78v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> script, ScriptExecutionContext* context) 79{ 80 TRACE_EVENT0("v8", "v8.run"); 81 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 82 if (script.IsEmpty()) 83 return v8::Local<v8::Value>(); 84 85 if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) 86 return handleMaxRecursionDepthExceeded(); 87 88 if (handleOutOfMemory()) 89 return v8::Local<v8::Value>(); 90 91 // Run the script and keep track of the current recursion depth. 92 v8::Local<v8::Value> result; 93 { 94 V8RecursionScope recursionScope(context); 95 result = script->Run(); 96 } 97 98 if (handleOutOfMemory()) 99 ASSERT(result.IsEmpty()); 100 101 if (result.IsEmpty()) 102 return v8::Local<v8::Value>(); 103 104 crashIfV8IsDead(); 105 return result; 106} 107 108v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData) 109{ 110 TRACE_EVENT0("v8", "v8.run"); 111 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 112 v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, scriptData, isolate); 113 if (script.IsEmpty()) 114 return v8::Local<v8::Value>(); 115 116 V8RecursionScope::MicrotaskSuppression recursionScope; 117 v8::Local<v8::Value> result = script->Run(); 118 crashIfV8IsDead(); 119 return result; 120} 121 122v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ScriptExecutionContext* context, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) 123{ 124 TRACE_EVENT0("v8", "v8.callFunction"); 125 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 126 127 if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) 128 return handleMaxRecursionDepthExceeded(); 129 130 V8RecursionScope recursionScope(context); 131 v8::Local<v8::Value> result = function->Call(receiver, argc, args); 132 crashIfV8IsDead(); 133 return result; 134} 135 136v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate) 137{ 138 TRACE_EVENT0("v8", "v8.callFunction"); 139 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 140 V8RecursionScope::MicrotaskSuppression recursionScope; 141 v8::Local<v8::Value> result = function->Call(receiver, argc, args); 142 crashIfV8IsDead(); 143 return result; 144} 145 146v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Handle<v8::Object> object, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) 147{ 148 TRACE_EVENT0("v8", "v8.callFunction"); 149 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 150 V8RecursionScope::MicrotaskSuppression recursionScope; 151 v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, args); 152 crashIfV8IsDead(); 153 return result; 154} 155 156v8::Local<v8::Value> V8ScriptRunner::callAsConstructor(v8::Handle<v8::Object> object, int argc, v8::Handle<v8::Value> args[]) 157{ 158 TRACE_EVENT0("v8", "v8.callFunction"); 159 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 160 V8RecursionScope::MicrotaskSuppression recursionScope; 161 v8::Local<v8::Value> result = object->CallAsConstructor(argc, args); 162 crashIfV8IsDead(); 163 return result; 164} 165 166v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate) 167{ 168 TRACE_EVENT0("v8", "v8.newInstance"); 169 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 170 V8RecursionScope::MicrotaskSuppression scope; 171 v8::Local<v8::Object> result = objectTemplate->NewInstance(); 172 crashIfV8IsDead(); 173 return result; 174} 175 176v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) 177{ 178 TRACE_EVENT0("v8", "v8.newInstance"); 179 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 180 V8RecursionScope::MicrotaskSuppression scope; 181 v8::Local<v8::Object> result = function->NewInstance(argc, argv); 182 crashIfV8IsDead(); 183 return result; 184} 185 186v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Handle<v8::Function> function, ScriptExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) 187{ 188 TRACE_EVENT0("v8", "v8.newInstance"); 189 TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); 190 V8RecursionScope scope(context); 191 v8::Local<v8::Object> result = function->NewInstance(argc, argv); 192 crashIfV8IsDead(); 193 return result; 194} 195 196} // namespace WebCore 197