| 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 |