blob: 8b0b0729797427ce6bf7291fe997d98b93a29f8e [file] [log] [blame]
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +00001
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
12using namespace v8;
13
14#include "Global.h"
15#include "JsContext.h"
commit-bot@chromium.orgf679d1b2014-02-27 20:20:21 +000016#include "Path2D.h"
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000017#include "SkCanvas.h"
18
19
20// Extracts a C string from a V8 Utf8Value.
21// TODO(jcgregrio) Currently dup'd in two files, fix.
22static const char* to_cstring(const v8::String::Utf8Value& value) {
23 return *value ? *value : "<string conversion failed>";
24}
25
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000026Persistent<ObjectTemplate> JsContext::gContextTemplate;
27
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000028// Wraps 'this' in a Javascript object.
29Handle<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()) {
commit-bot@chromium.org24e04962014-03-04 20:44:32 +000036 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);
commit-bot@chromium.orgc8d73282014-01-06 18:17:24 +000044 }
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
65void 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.
110bool 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}