• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2013 Google Inc.
4  *
5  *
6  * Use of this source code is governed by a BSD-style license that can be
7  * found in the LICENSE file.
8  *
9  */
10 #include <v8.h>
11 
12 using namespace v8;
13 
14 #include "Global.h"
15 #include "JsContext.h"
16 #include "Path2D.h"
17 #include "SkCanvas.h"
18 
19 
20 // Extracts a C string from a V8 Utf8Value.
21 // TODO(jcgregrio) Currently dup'd in two files, fix.
to_cstring(const v8::String::Utf8Value & value)22 static const char* to_cstring(const v8::String::Utf8Value& value) {
23     return *value ? *value : "<string conversion failed>";
24 }
25 
26 Persistent<ObjectTemplate> JsContext::gContextTemplate;
27 
28 // Wraps 'this' in a Javascript object.
wrap()29 Handle<Object> JsContext::wrap() {
30     // Handle scope for temporary handles.
31     EscapableHandleScope handleScope(fGlobal->getIsolate());
32 
33     // Fetch the template for creating JavaScript JsContext wrappers.
34     // It only has to be created once, which we do on demand.
35     if (gContextTemplate.IsEmpty()) {
36         Local<ObjectTemplate> localTemplate = ObjectTemplate::New();
37 
38         // Add a field to store the pointer to a JsContext instance.
39         localTemplate->SetInternalFieldCount(1);
40 
41         this->addAttributesAndMethods(localTemplate);
42 
43         gContextTemplate.Reset(fGlobal->getIsolate(), localTemplate);
44     }
45     Handle<ObjectTemplate> templ =
46             Local<ObjectTemplate>::New(fGlobal->getIsolate(), gContextTemplate);
47 
48     // Create an empty JsContext wrapper.
49     Local<Object> result = templ->NewInstance();
50 
51     // Wrap the raw C++ pointer in an External so it can be referenced
52     // from within JavaScript.
53     Handle<External> contextPtr = External::New(fGlobal->getIsolate(), this);
54 
55     // Store the context pointer in the JavaScript wrapper.
56     result->SetInternalField(0, contextPtr);
57 
58     // Return the result through the current handle scope.  Since each
59     // of these handles will go away when the handle scope is deleted
60     // we need to call Close to let one, the result, escape into the
61     // outer handle scope.
62     return handleScope.Escape(result);
63 }
64 
onDraw(SkCanvas * canvas)65 void JsContext::onDraw(SkCanvas* canvas) {
66     // Record canvas and window in this.
67     fCanvas = canvas;
68 
69     // Create a handle scope to keep the temporary object references.
70     HandleScope handleScope(fGlobal->getIsolate());
71 
72     // Create a local context from our global context.
73     Local<Context> context = fGlobal->getContext();
74 
75     // Enter the context so all the remaining operations take place there.
76     Context::Scope contextScope(context);
77 
78     // Wrap the C++ this pointer in a JavaScript wrapper.
79     Handle<Object> contextObj = this->wrap();
80 
81     // Set up an exception handler before calling the Process function.
82     TryCatch tryCatch;
83 
84     // Invoke the process function, giving the global object as 'this'
85     // and one argument, this JsContext.
86     const int argc = 1;
87     Handle<Value> argv[argc] = { contextObj };
88     Local<Function> onDraw =
89             Local<Function>::New(fGlobal->getIsolate(), fOnDraw);
90     Handle<Value> result = onDraw->Call(context->Global(), argc, argv);
91 
92     // Handle any exceptions or output.
93     if (result.IsEmpty()) {
94         SkASSERT(tryCatch.HasCaught());
95         // Print errors that happened during execution.
96         fGlobal->reportException(&tryCatch);
97     } else {
98         SkASSERT(!tryCatch.HasCaught());
99         if (!result->IsUndefined()) {
100             // If all went well and the result wasn't undefined then print
101             // the returned value.
102             String::Utf8Value str(result);
103             const char* cstr = to_cstring(str);
104             printf("%s\n", cstr);
105         }
106     }
107 }
108 
109 // Fetch the onDraw function from the global context.
initialize()110 bool JsContext::initialize() {
111 
112     // Create a stack-allocated handle scope.
113     HandleScope handleScope(fGlobal->getIsolate());
114 
115     // Create a local context from our global context.
116     Local<Context> context = fGlobal->getContext();
117 
118     // Enter the scope so all operations take place in the scope.
119     Context::Scope contextScope(context);
120 
121     v8::TryCatch try_catch;
122 
123     Handle<String> fn_name = String::NewFromUtf8(
124         fGlobal->getIsolate(), "onDraw");
125     Handle<Value> fn_val = context->Global()->Get(fn_name);
126 
127     if (!fn_val->IsFunction()) {
128         printf("Not a function.\n");
129         return false;
130     }
131 
132     // It is a function; cast it to a Function.
133     Handle<Function> fn_fun = Handle<Function>::Cast(fn_val);
134 
135     // Store the function in a Persistent handle, since we also want that to
136     // remain after this call returns.
137     fOnDraw.Reset(fGlobal->getIsolate(), fn_fun);
138 
139     return true;
140 }
141