OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 * | 7 * |
8 */ | 8 */ |
9 #include "Global.h" | 9 #include "Global.h" |
10 | 10 |
11 #include "SkWindow.h" | 11 #include "SkWindow.h" |
12 #include "SkEvent.h" | 12 #include "SkEvent.h" |
13 | 13 |
14 | 14 |
15 Global* Global::gGlobal = NULL; | 15 Global* Global::gGlobal = NULL; |
16 | 16 |
17 // Extracts a C string from a V8 Utf8Value. | 17 // Extracts a C string from a V8 Utf8Value. |
18 static const char* to_cstring(const v8::String::Utf8Value& value) { | 18 static const char* to_cstring(const v8::String::Utf8Value& value) { |
19 return *value ? *value : "<string conversion failed>"; | 19 return *value ? *value : "<string conversion failed>"; |
20 } | 20 } |
21 | 21 |
| 22 int32_t Global::getNextTimerID() { |
| 23 do { |
| 24 fLastTimerID++; |
| 25 if (fLastTimerID < 0) { |
| 26 fLastTimerID = 0; |
| 27 } |
| 28 } while (fTimeouts.find(fLastTimerID) != fTimeouts.end()); |
| 29 return fLastTimerID; |
| 30 } |
| 31 |
22 // Slight modification to an original function found in the V8 sample shell.cc. | 32 // Slight modification to an original function found in the V8 sample shell.cc. |
23 void Global::reportException(TryCatch* tryCatch) { | 33 void Global::reportException(TryCatch* tryCatch) { |
24 HandleScope handleScope(fIsolate); | 34 HandleScope handleScope(fIsolate); |
25 String::Utf8Value exception(tryCatch->Exception()); | 35 String::Utf8Value exception(tryCatch->Exception()); |
26 const char* exceptionString = to_cstring(exception); | 36 const char* exceptionString = to_cstring(exception); |
27 Handle<Message> message = tryCatch->Message(); | 37 Handle<Message> message = tryCatch->Message(); |
28 if (message.IsEmpty()) { | 38 if (message.IsEmpty()) { |
29 // V8 didn't provide any extra information about this error; just | 39 // V8 didn't provide any extra information about this error; just |
30 // print the exception. | 40 // print the exception. |
31 fprintf(stderr, "%s\n", exceptionString); | 41 fprintf(stderr, "%s\n", exceptionString); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 printf("%s", to_cstring(str)); | 94 printf("%s", to_cstring(str)); |
85 } | 95 } |
86 printf("\n"); | 96 printf("\n"); |
87 fflush(stdout); | 97 fflush(stdout); |
88 } | 98 } |
89 | 99 |
90 // The callback that is invoked by v8 whenever the JavaScript 'setTimeout' | 100 // The callback that is invoked by v8 whenever the JavaScript 'setTimeout' |
91 // function is called. | 101 // function is called. |
92 // | 102 // |
93 // JS: setTimeout(on_timeout, 500); | 103 // JS: setTimeout(on_timeout, 500); |
94 // | |
95 // TODO(jcgregorio) Currently only handles one timeout, should support any | |
96 // number. | |
97 void Global::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { | 104 void Global::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { |
98 if (args.Length() != 2) { | 105 if (args.Length() != 2) { |
99 args.GetIsolate()->ThrowException( | 106 args.GetIsolate()->ThrowException( |
100 v8::String::NewFromUtf8( | 107 v8::String::NewFromUtf8( |
101 args.GetIsolate(), "Error: 2 arguments required.")); | 108 args.GetIsolate(), "Error: 2 arguments required.")); |
102 return; | 109 return; |
103 } | 110 } |
104 | 111 |
105 // Pull out the first arg, make sure it's a function. | 112 // Pull out the first arg, make sure it's a function. |
106 if (!args[0]->IsFunction()) { | 113 if (!args[0]->IsFunction()) { |
107 printf("Not a function passed to setTimeout.\n"); | 114 printf("Not a function passed to setTimeout.\n"); |
108 return; | 115 return; |
109 } | 116 } |
110 Handle<Function> timeoutFn = Handle<Function>::Cast(args[0]); | 117 Handle<Function> timeoutFn = Handle<Function>::Cast(args[0]); |
111 gGlobal->fTimeout.Reset(args.GetIsolate(), timeoutFn); | |
112 | 118 |
113 double delay = args[1]->NumberValue(); | 119 double delay = args[1]->NumberValue(); |
| 120 int32_t id = gGlobal->getNextTimerID(); |
| 121 |
| 122 gGlobal->fTimeouts[id].Reset(gGlobal->fIsolate, timeoutFn); |
114 | 123 |
115 // Create an SkEvent and add it with the right delay. | 124 // Create an SkEvent and add it with the right delay. |
116 (new SkEvent())->setTargetProc(Global::TimeOutProc)->postDelay(delay); | 125 SkEvent* evt = new SkEvent(); |
| 126 evt->setTargetProc(Global::TimeOutProc); |
| 127 evt->setFast32(id); |
| 128 evt->postDelay(delay); |
117 | 129 |
118 // TODO(jcgregorio) Return the ID as the return value. | 130 args.GetReturnValue().Set(Integer::New(id)); |
119 } | 131 } |
120 | 132 |
121 // Callback function for SkEvents used to implement timeouts. | 133 // Callback function for SkEvents used to implement timeouts. |
122 bool Global::TimeOutProc(const SkEvent& evt) { | 134 bool Global::TimeOutProc(const SkEvent& evt) { |
123 // Create a handle scope to keep the temporary object references. | 135 // Create a handle scope to keep the temporary object references. |
124 HandleScope handleScope(gGlobal->getIsolate()); | 136 HandleScope handleScope(gGlobal->getIsolate()); |
125 | 137 |
126 // Create a local context from our global context. | 138 // Create a local context from our global context. |
127 Local<Context> context = gGlobal->getContext(); | 139 Local<Context> context = gGlobal->getContext(); |
128 | 140 |
129 // Enter the context so all the remaining operations take place there. | 141 // Enter the context so all the remaining operations take place there. |
130 Context::Scope contextScope(context); | 142 Context::Scope contextScope(context); |
131 | 143 |
132 // Set up an exception handler before calling the Process function. | 144 // Set up an exception handler before calling the Process function. |
133 TryCatch tryCatch; | 145 TryCatch tryCatch; |
134 | 146 |
| 147 int32_t id = evt.getFast32(); |
| 148 if (gGlobal->fTimeouts.find(gGlobal->fLastTimerID) == gGlobal->fTimeouts.end
()) { |
| 149 printf("Not a valid timer ID.\n"); |
| 150 return true; |
| 151 } |
| 152 |
135 const int argc = 0; | 153 const int argc = 0; |
136 Local<Function> onTimeout = | 154 Local<Function> onTimeout = |
137 Local<Function>::New(gGlobal->getIsolate(), gGlobal->fTimeout); | 155 Local<Function>::New(gGlobal->getIsolate(), gGlobal->fTimeouts[id]); |
138 Handle<Value> result = onTimeout->Call(context->Global(), argc, NULL); | 156 Handle<Value> result = onTimeout->Call(context->Global(), argc, NULL); |
| 157 gGlobal->fTimeouts.erase(id); |
139 | 158 |
140 // Handle any exceptions or output. | 159 // Handle any exceptions or output. |
141 if (result.IsEmpty()) { | 160 if (result.IsEmpty()) { |
142 SkASSERT(tryCatch.HasCaught()); | 161 SkASSERT(tryCatch.HasCaught()); |
143 // Print errors that happened during execution. | 162 // Print errors that happened during execution. |
144 gGlobal->reportException(&tryCatch); | 163 gGlobal->reportException(&tryCatch); |
145 } else { | 164 } else { |
146 SkASSERT(!tryCatch.HasCaught()); | 165 SkASSERT(!tryCatch.HasCaught()); |
147 if (!result->IsUndefined()) { | 166 if (!result->IsUndefined()) { |
148 // If all went well and the result wasn't undefined then print the | 167 // If all went well and the result wasn't undefined then print the |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 | 226 |
208 // Try running it now to create the onDraw function. | 227 // Try running it now to create the onDraw function. |
209 Handle<Value> result = compiledScript->Run(); | 228 Handle<Value> result = compiledScript->Run(); |
210 | 229 |
211 // Handle any exceptions or output. | 230 // Handle any exceptions or output. |
212 if (result.IsEmpty()) { | 231 if (result.IsEmpty()) { |
213 SkASSERT(tryCatch.HasCaught()); | 232 SkASSERT(tryCatch.HasCaught()); |
214 // Print errors that happened during execution. | 233 // Print errors that happened during execution. |
215 this->reportException(&tryCatch); | 234 this->reportException(&tryCatch); |
216 return false; | 235 return false; |
217 } else { | |
218 SkASSERT(!tryCatch.HasCaught()); | |
219 if (!result->IsUndefined()) { | |
220 // If all went well and the result wasn't undefined then print | |
221 // the returned value. | |
222 String::Utf8Value str(result); | |
223 const char* cstr = to_cstring(str); | |
224 printf("%s\n", cstr); | |
225 return false; | |
226 } | |
227 } | 236 } |
228 | 237 |
229 // Also make the context persistent. | 238 // Also make the context persistent. |
230 fContext.Reset(fIsolate, context); | 239 fContext.Reset(fIsolate, context); |
231 return true; | 240 return true; |
232 } | 241 } |
OLD | NEW |