OLD | NEW |
---|---|
(Empty) | |
1 #include "Global.h" | |
robertphillips
2013/12/17 23:35:53
Header!
jcgregorio
2013/12/18 04:32:53
Done.
| |
2 | |
3 #include "SkWindow.h" | |
4 #include "SkEvent.h" | |
5 | |
6 | |
7 Global* Global::gGlobal = NULL; | |
8 | |
9 // Extracts a C string from a V8 Utf8Value. | |
robertphillips
2013/12/17 23:35:53
to_cstring?
jcgregorio
2013/12/18 04:32:53
Done.
| |
10 static const char* ToCString(const v8::String::Utf8Value& value) { | |
11 return *value ? *value : "<string conversion failed>"; | |
12 } | |
13 | |
14 // Slight modification to an original function found in the V8 sample shell.cc. | |
robertphillips
2013/12/17 23:35:53
tryCatch?
jcgregorio
2013/12/18 04:32:53
Done.
| |
15 void Global::reportException(TryCatch* try_catch) { | |
16 HandleScope handleScope(fIsolate); | |
17 String::Utf8Value exception(try_catch->Exception()); | |
robertphillips
2013/12/17 23:35:53
exceptionString?
jcgregorio
2013/12/18 04:32:53
Done.
| |
18 const char* exception_string = ToCString(exception); | |
19 Handle<Message> message = try_catch->Message(); | |
20 if (message.IsEmpty()) { | |
21 // V8 didn't provide any extra information about this error; just | |
22 // print the exception. | |
23 fprintf(stderr, "%s\n", exception_string); | |
24 } else { | |
25 // Print (filename):(line number): (message). | |
26 String::Utf8Value filename(message->GetScriptResourceName()); | |
robertphillips
2013/12/17 23:35:53
filenameString?
jcgregorio
2013/12/18 04:32:53
Done.
| |
27 const char* filename_string = ToCString(filename); | |
28 int linenum = message->GetLineNumber(); | |
29 fprintf(stderr, | |
30 "%s:%i: %s\n", filename_string, linenum, exception_string); | |
31 // Print line of source code. | |
32 String::Utf8Value sourceline(message->GetSourceLine()); | |
robertphillips
2013/12/17 23:35:53
sourceLineString?
jcgregorio
2013/12/18 04:32:53
Done.
| |
33 const char* sourceline_string = ToCString(sourceline); | |
34 fprintf(stderr, "%s\n", sourceline_string); | |
35 // Print wavy underline. | |
36 int start = message->GetStartColumn(); | |
37 for (int i = 0; i < start; i++) { | |
38 fprintf(stderr, " "); | |
39 } | |
40 int end = message->GetEndColumn(); | |
41 for (int i = start; i < end; i++) { | |
42 fprintf(stderr, "^"); | |
43 } | |
44 fprintf(stderr, "\n"); | |
45 String::Utf8Value stack_trace(try_catch->StackTrace()); | |
46 if (stack_trace.length() > 0) { | |
robertphillips
2013/12/17 23:35:53
stackTraceString?
jcgregorio
2013/12/18 04:32:53
Done.
| |
47 const char* stack_trace_string = ToCString(stack_trace); | |
48 fprintf(stderr, "%s\n", stack_trace_string); | |
49 } | |
50 } | |
51 } | |
52 | |
53 // The callback that implements the JavaScript 'inval' function. | |
54 // Invalidates the current window, forcing a redraw. | |
55 // | |
56 // JS: inval(); | |
57 void Global::Inval(const v8::FunctionCallbackInfo<Value>& args) { | |
58 gGlobal->getWindow()->inval(NULL); | |
59 } | |
60 | |
61 // The callback that is invoked by v8 whenever the JavaScript 'print' | |
62 // function is called. Prints its arguments on stdout separated by | |
63 // spaces and ending with a newline. | |
64 // | |
65 // JS: print("foo", "bar"); | |
66 void Global::Print(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
67 bool first = true; | |
robertphillips
2013/12/17 23:35:53
handleScope?
jcgregorio
2013/12/18 04:32:53
Done.
| |
68 HandleScope handle_scope(args.GetIsolate()); | |
69 for (int i = 0; i < args.Length(); i++) { | |
70 if (first) { | |
71 first = false; | |
72 } else { | |
73 printf(" "); | |
74 } | |
75 v8::String::Utf8Value str(args[i]); | |
76 printf("%s", ToCString(str)); | |
77 } | |
78 printf("\n"); | |
79 fflush(stdout); | |
80 } | |
81 | |
82 // The callback that is invoked by v8 whenever the JavaScript 'setTimeout' | |
83 // function is called. | |
84 // | |
85 // JS: setTimeout(on_timeout, 500); | |
86 // | |
87 // TODO(jcgregorio) Currently only handles one timeout, should support any | |
88 // number. | |
89 void Global::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
90 if (args.Length() != 2) { | |
91 args.GetIsolate()->ThrowException( | |
92 v8::String::NewFromUtf8( | |
93 args.GetIsolate(), "Error: 2 arguments required.")); | |
94 return; | |
95 } | |
96 | |
97 // Pull out the first arg, make sure it's a function. | |
98 if (!args[0]->IsFunction()) { | |
99 printf("Not a function passed to setTimeout.\n"); | |
100 return; | |
101 } | |
robertphillips
2013/12/17 23:35:53
timeoutFn?
jcgregorio
2013/12/18 04:32:53
Done.
| |
102 Handle<Function> timeout_fn = Handle<Function>::Cast(args[0]); | |
103 gGlobal->fTimeout.Reset(args.GetIsolate(), timeout_fn); | |
104 | |
105 double delay = args[1]->NumberValue(); | |
106 | |
107 // Create an SkEvent and add it with the right delay. | |
108 (new SkEvent())->setTargetProc(Global::TimeOutProc)->postDelay(delay); | |
109 | |
110 // TODO(jcgregorio) Return the ID as the return value. | |
111 } | |
112 | |
113 // Callback function for SkEvents used to implement timeouts. | |
114 bool Global::TimeOutProc(const SkEvent& evt) { | |
115 // Create a handle scope to keep the temporary object references. | |
116 HandleScope handleScope(gGlobal->getIsolate()); | |
117 | |
118 // Create a local context from our global context. | |
119 Local<Context> context = gGlobal->getContext(); | |
120 | |
121 // Enter the context so all the remaining operations take place there. | |
122 Context::Scope contextScope(context); | |
123 | |
124 // Set up an exception handler before calling the Process function. | |
125 TryCatch tryCatch; | |
126 | |
127 const int argc = 0; | |
128 Local<Function> onTimeout = | |
129 Local<Function>::New(gGlobal->getIsolate(), gGlobal->fTimeout); | |
130 Handle<Value> result = onTimeout->Call(context->Global(), argc, NULL); | |
131 | |
132 // Handle any exceptions or output. | |
133 if (result.IsEmpty()) { | |
134 SkASSERT(tryCatch.HasCaught()); | |
135 // Print errors that happened during execution. | |
136 gGlobal->reportException(&tryCatch); | |
137 } else { | |
138 SkASSERT(!tryCatch.HasCaught()); | |
139 if (!result->IsUndefined()) { | |
140 // If all went well and the result wasn't undefined then print the | |
141 // returned value. | |
142 String::Utf8Value str(result); | |
143 const char* cstr = ToCString(str); | |
144 printf("%s\n", cstr); | |
145 } | |
146 } | |
147 return true; | |
148 } | |
149 | |
150 // Creates a new execution environment containing the built-in functions. | |
151 Handle<Context> Global::createRootContext() { | |
152 // Create a template for the global object. | |
153 Handle<ObjectTemplate> global = ObjectTemplate::New(); | |
154 | |
155 global->Set(v8::String::NewFromUtf8(fIsolate, "print"), | |
156 v8::FunctionTemplate::New(Global::Print)); | |
157 global->Set(v8::String::NewFromUtf8(fIsolate, "setTimeout"), | |
158 v8::FunctionTemplate::New(Global::SetTimeout)); | |
159 global->Set(v8::String::NewFromUtf8(fIsolate, "inval"), | |
160 v8::FunctionTemplate::New(Global::Inval)); | |
161 | |
162 | |
163 return Context::New(fIsolate, NULL, global); | |
164 } | |
165 | |
166 | |
167 // Creates the root context, parses the script into it, then stores the | |
168 // context in a global. | |
169 // | |
170 // TODO(jcgregorio) Currently only handles one script. Need to move | |
171 // createRootContext to another call that's only done once. | |
172 bool Global::parseScript(const char script[]) { | |
173 | |
174 // Create a stack-allocated handle scope. | |
175 HandleScope handleScope(fIsolate); | |
176 | |
177 printf("Before create context\n"); | |
178 | |
179 // Create a new context. | |
180 Handle<Context> context = this->createRootContext(); | |
181 | |
182 // Enter the scope so all operations take place in the scope. | |
183 Context::Scope contextScope(context); | |
184 | |
robertphillips
2013/12/17 23:35:53
tryCatch?
jcgregorio
2013/12/18 04:32:53
Done.
| |
185 v8::TryCatch try_catch; | |
186 | |
187 // Compile the source code. | |
188 Handle<String> source = String::NewFromUtf8(fIsolate, script); | |
189 printf("Before Compile\n"); | |
robertphillips
2013/12/17 23:35:53
compiledScript?
jcgregorio
2013/12/18 04:32:53
Done.
| |
190 Handle<Script> compiled_script = Script::Compile(source); | |
191 printf("After Compile\n"); | |
192 | |
193 if (compiled_script.IsEmpty()) { | |
194 // Print errors that happened during compilation. | |
195 this->reportException(&try_catch); | |
196 return false; | |
197 } | |
198 printf("After Exception.\n"); | |
199 | |
200 // Try running it now to create the onDraw function. | |
201 Handle<Value> result = compiled_script->Run(); | |
202 | |
203 // Handle any exceptions or output. | |
204 if (result.IsEmpty()) { | |
205 SkASSERT(try_catch.HasCaught()); | |
206 // Print errors that happened during execution. | |
207 this->reportException(&try_catch); | |
208 return false; | |
209 } else { | |
210 SkASSERT(!try_catch.HasCaught()); | |
211 if (!result->IsUndefined()) { | |
212 // If all went well and the result wasn't undefined then print | |
213 // the returned value. | |
214 String::Utf8Value str(result); | |
215 const char* cstr = ToCString(str); | |
216 printf("%s\n", cstr); | |
217 return false; | |
218 } | |
219 } | |
220 | |
221 // Also make the context persistent. | |
222 fContext.Reset(fIsolate, context); | |
223 return true; | |
224 } | |
OLD | NEW |