• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ExecutionContext.h"
33 #include "core/fetch/CachedMetadata.h"
34 #include "core/fetch/ScriptResource.h"
35 #include "platform/TraceEvent.h"
36 
37 namespace WebCore {
38 
precompileScript(v8::Handle<v8::String> code,ScriptResource * resource)39 PassOwnPtr<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 
compileScript(v8::Handle<v8::String> code,const String & fileName,const TextPosition & scriptStartPosition,v8::ScriptData * scriptData,v8::Isolate * isolate,AccessControlStatus corsStatus)66 v8::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(isolate, fileName);
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(isolate) : v8::False(isolate);
74     v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin);
75     return v8::Script::Compile(code, &origin, scriptData);
76 }
77 
runCompiledScript(v8::Handle<v8::Script> script,ExecutionContext * context,v8::Isolate * isolate)78 v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> script, ExecutionContext* context, v8::Isolate* isolate)
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(isolate);
87 
88     if (handleOutOfMemory())
89         return v8::Local<v8::Value>();
90 
91     RELEASE_ASSERT(!context->isIteratingOverObservers());
92 
93     // Run the script and keep track of the current recursion depth.
94     v8::Local<v8::Value> result;
95     {
96         V8RecursionScope recursionScope(context);
97         result = script->Run();
98     }
99 
100     if (handleOutOfMemory())
101         ASSERT(result.IsEmpty());
102 
103     if (result.IsEmpty())
104         return v8::Local<v8::Value>();
105 
106     crashIfV8IsDead();
107     return result;
108 }
109 
compileAndRunInternalScript(v8::Handle<v8::String> source,v8::Isolate * isolate,const String & fileName,const TextPosition & scriptStartPosition,v8::ScriptData * scriptData)110 v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData)
111 {
112     TRACE_EVENT0("v8", "v8.run");
113     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
114     v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, scriptData, isolate);
115     if (script.IsEmpty())
116         return v8::Local<v8::Value>();
117 
118     V8RecursionScope::MicrotaskSuppression recursionScope;
119     v8::Local<v8::Value> result = script->Run();
120     crashIfV8IsDead();
121     return result;
122 }
123 
callFunction(v8::Handle<v8::Function> function,ExecutionContext * context,v8::Handle<v8::Value> receiver,int argc,v8::Handle<v8::Value> info[],v8::Isolate * isolate)124 v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate)
125 {
126     TRACE_EVENT0("v8", "v8.callFunction");
127     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
128 
129     if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth)
130         return handleMaxRecursionDepthExceeded(isolate);
131 
132     RELEASE_ASSERT(!context->isIteratingOverObservers());
133 
134     V8RecursionScope recursionScope(context);
135     v8::Local<v8::Value> result = function->Call(receiver, argc, info);
136     crashIfV8IsDead();
137     return result;
138 }
139 
callInternalFunction(v8::Handle<v8::Function> function,v8::Handle<v8::Value> receiver,int argc,v8::Handle<v8::Value> info[],v8::Isolate * isolate)140 v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate)
141 {
142     TRACE_EVENT0("v8", "v8.callFunction");
143     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
144     V8RecursionScope::MicrotaskSuppression recursionScope;
145     v8::Local<v8::Value> result = function->Call(receiver, argc, info);
146     crashIfV8IsDead();
147     return result;
148 }
149 
callAsFunction(v8::Handle<v8::Object> object,v8::Handle<v8::Value> receiver,int argc,v8::Handle<v8::Value> info[])150 v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Handle<v8::Object> object, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[])
151 {
152     TRACE_EVENT0("v8", "v8.callFunction");
153     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
154 
155     V8RecursionScope::MicrotaskSuppression recursionScope;
156     v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, info);
157     crashIfV8IsDead();
158     return result;
159 }
160 
callAsConstructor(v8::Handle<v8::Object> object,int argc,v8::Handle<v8::Value> info[])161 v8::Local<v8::Value> V8ScriptRunner::callAsConstructor(v8::Handle<v8::Object> object, int argc, v8::Handle<v8::Value> info[])
162 {
163     TRACE_EVENT0("v8", "v8.callFunction");
164     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
165 
166     V8RecursionScope::MicrotaskSuppression recursionScope;
167     v8::Local<v8::Value> result = object->CallAsConstructor(argc, info);
168     crashIfV8IsDead();
169     return result;
170 }
171 
instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate)172 v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate)
173 {
174     TRACE_EVENT0("v8", "v8.newInstance");
175     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
176 
177     V8RecursionScope::MicrotaskSuppression scope;
178     v8::Local<v8::Object> result = objectTemplate->NewInstance();
179     crashIfV8IsDead();
180     return result;
181 }
182 
instantiateObject(v8::Handle<v8::Function> function,int argc,v8::Handle<v8::Value> argv[])183 v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[])
184 {
185     TRACE_EVENT0("v8", "v8.newInstance");
186     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
187 
188     V8RecursionScope::MicrotaskSuppression scope;
189     v8::Local<v8::Object> result = function->NewInstance(argc, argv);
190     crashIfV8IsDead();
191     return result;
192 }
193 
instantiateObjectInDocument(v8::Handle<v8::Function> function,ExecutionContext * context,int argc,v8::Handle<v8::Value> argv[])194 v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[])
195 {
196     TRACE_EVENT0("v8", "v8.newInstance");
197     TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
198     V8RecursionScope scope(context);
199     v8::Local<v8::Object> result = function->NewInstance(argc, argv);
200     crashIfV8IsDead();
201     return result;
202 }
203 
204 } // namespace WebCore
205