10fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org/*
20fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org * Copyright 2013 Google Inc.
30fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org *
40fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org *
50fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
60fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org * found in the LICENSE file.
70fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org *
80fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org */
90fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org#include "Global.h"
100fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
110fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org#include "SkWindow.h"
120fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org#include "SkEvent.h"
130fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
140fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
150fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgGlobal* Global::gGlobal = NULL;
160fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
170fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Extracts a C string from a V8 Utf8Value.
180fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgstatic const char* to_cstring(const v8::String::Utf8Value& value) {
190fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    return *value ? *value : "<string conversion failed>";
200fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
210fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
22872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.orgint32_t Global::getNextTimerID() {
23872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    do {
24872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org        fLastTimerID++;
25872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org        if (fLastTimerID < 0) {
26872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org            fLastTimerID = 0;
27872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org        }
28872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    } while (fTimeouts.find(fLastTimerID) != fTimeouts.end());
29872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    return fLastTimerID;
30872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org}
31872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org
320fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Slight modification to an original function found in the V8 sample shell.cc.
330fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgvoid Global::reportException(TryCatch* tryCatch) {
340fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    HandleScope handleScope(fIsolate);
350fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    String::Utf8Value exception(tryCatch->Exception());
360fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    const char* exceptionString = to_cstring(exception);
370fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<Message> message = tryCatch->Message();
380fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (message.IsEmpty()) {
390fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // V8 didn't provide any extra information about this error; just
400fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // print the exception.
410fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        fprintf(stderr, "%s\n", exceptionString);
420fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    } else {
430fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print (filename):(line number): (message).
44c09e8c2ec9c5cdd9e147b6f48527970b4518fb76kozyatinskiy        String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
450fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        const char* filenameString = to_cstring(filename);
460fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        int linenum = message->GetLineNumber();
470fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        fprintf(stderr,
480fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org                "%s:%i: %s\n", filenameString, linenum, exceptionString);
490fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print line of source code.
500fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        String::Utf8Value sourceline(message->GetSourceLine());
510fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        const char* sourceLineString = to_cstring(sourceline);
520fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        fprintf(stderr, "%s\n", sourceLineString);
530fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print wavy underline.
540fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        int start = message->GetStartColumn();
550fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        for (int i = 0; i < start; i++) {
560fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            fprintf(stderr, " ");
570fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        }
580fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        int end = message->GetEndColumn();
590fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        for (int i = start; i < end; i++) {
600fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            fprintf(stderr, "^");
610fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        }
620fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        fprintf(stderr, "\n");
630fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        String::Utf8Value stackTrace(tryCatch->StackTrace());
640fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        if (stackTrace.length() > 0) {
650fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            const char* stackTraceString = to_cstring(stackTrace);
660fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            fprintf(stderr, "%s\n", stackTraceString);
670fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        }
680fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
690fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
700fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
710fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// The callback that implements the JavaScript 'inval' function.
720fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Invalidates the current window, forcing a redraw.
730fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org//
740fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// JS: inval();
750fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgvoid Global::Inval(const v8::FunctionCallbackInfo<Value>& args) {
760fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    gGlobal->getWindow()->inval(NULL);
770fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
780fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
790fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// The callback that is invoked by v8 whenever the JavaScript 'print'
800fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// function is called. Prints its arguments on stdout separated by
810fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// spaces and ending with a newline.
820fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org//
830fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// JS: print("foo", "bar");
840fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgvoid Global::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
850fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    bool first = true;
860fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    HandleScope handleScope(args.GetIsolate());
870fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    for (int i = 0; i < args.Length(); i++) {
880fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        if (first) {
890fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            first = false;
900fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        } else {
910fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            printf(" ");
920fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        }
930fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        v8::String::Utf8Value str(args[i]);
940fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        printf("%s", to_cstring(str));
950fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
960fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    printf("\n");
970fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    fflush(stdout);
980fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
990fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1000fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// The callback that is invoked by v8 whenever the JavaScript 'setTimeout'
1010fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// function is called.
1020fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org//
1030fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// JS: setTimeout(on_timeout, 500);
1040fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgvoid Global::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
1050fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (args.Length() != 2) {
1060fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        args.GetIsolate()->ThrowException(
1070fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org                v8::String::NewFromUtf8(
1080fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org                        args.GetIsolate(), "Error: 2 arguments required."));
1090fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        return;
1100fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
1110fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1120fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Pull out the first arg, make sure it's a function.
1130fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (!args[0]->IsFunction()) {
1140fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        printf("Not a function passed to setTimeout.\n");
1150fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        return;
1160fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
1170fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<Function> timeoutFn = Handle<Function>::Cast(args[0]);
1180fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1190fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    double delay = args[1]->NumberValue();
120872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    int32_t id = gGlobal->getNextTimerID();
121872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org
122872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    gGlobal->fTimeouts[id].Reset(gGlobal->fIsolate, timeoutFn);
1230fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1240fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Create an SkEvent and add it with the right delay.
125872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    SkEvent* evt = new SkEvent();
126872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    evt->setTargetProc(Global::TimeOutProc);
127872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    evt->setFast32(id);
128872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    evt->postDelay(delay);
1290fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
130b163984ae775ae229b8f7fc5573f9d28eaf33c19commit-bot@chromium.org    args.GetReturnValue().Set(Integer::New(gGlobal->fIsolate, id));
1310fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
1320fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1330fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Callback function for SkEvents used to implement timeouts.
1340fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgbool Global::TimeOutProc(const SkEvent& evt) {
1350fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Create a handle scope to keep the temporary object references.
1360fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    HandleScope handleScope(gGlobal->getIsolate());
1370fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1380fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Create a local context from our global context.
1390fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Local<Context> context = gGlobal->getContext();
1400fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1410fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Enter the context so all the remaining operations take place there.
1420fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Context::Scope contextScope(context);
1430fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1440fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Set up an exception handler before calling the Process function.
1450fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    TryCatch tryCatch;
1460fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
147872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    int32_t id = evt.getFast32();
148872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    if (gGlobal->fTimeouts.find(gGlobal->fLastTimerID) == gGlobal->fTimeouts.end()) {
149872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org        printf("Not a valid timer ID.\n");
150872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org        return true;
151872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    }
152872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org
1530fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    const int argc = 0;
1540fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Local<Function> onTimeout =
155872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org            Local<Function>::New(gGlobal->getIsolate(), gGlobal->fTimeouts[id]);
1560fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<Value> result = onTimeout->Call(context->Global(), argc, NULL);
157872796bb8eaabbd9ab76dc8821310438aa690d85commit-bot@chromium.org    gGlobal->fTimeouts.erase(id);
1580fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1590fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Handle any exceptions or output.
1600fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (result.IsEmpty()) {
1610fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        SkASSERT(tryCatch.HasCaught());
1620fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print errors that happened during execution.
1630fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        gGlobal->reportException(&tryCatch);
1640fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    } else {
1650fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        SkASSERT(!tryCatch.HasCaught());
1660fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        if (!result->IsUndefined()) {
1670fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            // If all went well and the result wasn't undefined then print the
1680fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            // returned value.
1690fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            String::Utf8Value str(result);
1700fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            const char* cstr = to_cstring(str);
1710fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org            printf("%s\n", cstr);
1720fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        }
1730fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
1740fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    return true;
1750fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
1760fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1770fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Creates a new execution environment containing the built-in functions.
1780fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgHandle<Context> Global::createRootContext() {
1790fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  // Create a template for the global object.
1800fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  Handle<ObjectTemplate> global = ObjectTemplate::New();
1810fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1820fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  global->Set(v8::String::NewFromUtf8(fIsolate, "print"),
183b163984ae775ae229b8f7fc5573f9d28eaf33c19commit-bot@chromium.org              v8::FunctionTemplate::New(fIsolate, Global::Print));
1840fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  global->Set(v8::String::NewFromUtf8(fIsolate, "setTimeout"),
185b163984ae775ae229b8f7fc5573f9d28eaf33c19commit-bot@chromium.org              v8::FunctionTemplate::New(fIsolate, Global::SetTimeout));
1860fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  global->Set(v8::String::NewFromUtf8(fIsolate, "inval"),
187b163984ae775ae229b8f7fc5573f9d28eaf33c19commit-bot@chromium.org              v8::FunctionTemplate::New(fIsolate, Global::Inval));
1880fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1890fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
1900fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org  return Context::New(fIsolate, NULL, global);
1910fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
1920fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
193c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.orgvoid Global::initialize() {
194c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    // Create a stack-allocated handle scope.
195c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    HandleScope handleScope(fIsolate);
196c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org
197c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    // Create a new context.
198c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    Handle<Context> context = this->createRootContext();
199c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org
200c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    // Make the context persistent.
201c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    fContext.Reset(fIsolate, context);
202c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org}
203c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org
2040fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2050fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// Creates the root context, parses the script into it, then stores the
2060fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// context in a global.
2070fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org//
2080fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// TODO(jcgregorio) Currently only handles one script. Need to move
2090fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org// createRootContext to another call that's only done once.
2100fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.orgbool Global::parseScript(const char script[]) {
2110fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2120fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Create a stack-allocated handle scope.
2130fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    HandleScope handleScope(fIsolate);
2140fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
215c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    // Get the global context.
216c8d732800e1a660fca6d2478fc24d6e6935ef8adcommit-bot@chromium.org    Handle<Context> context = this->getContext();
2170fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2180fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Enter the scope so all operations take place in the scope.
2190fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Context::Scope contextScope(context);
2200fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2210fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    v8::TryCatch tryCatch;
2220fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2230fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Compile the source code.
2240fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<String> source = String::NewFromUtf8(fIsolate, script);
2250fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<Script> compiledScript = Script::Compile(source);
2260fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2270fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (compiledScript.IsEmpty()) {
2280fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print errors that happened during compilation.
2290fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        this->reportException(&tryCatch);
2300fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        return false;
2310fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
2320fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2330fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Try running it now to create the onDraw function.
2340fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    Handle<Value> result = compiledScript->Run();
2350fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2360fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    // Handle any exceptions or output.
2370fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    if (result.IsEmpty()) {
2380fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        SkASSERT(tryCatch.HasCaught());
2390fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        // Print errors that happened during execution.
2400fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        this->reportException(&tryCatch);
2410fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org        return false;
2420fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    }
2430fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org
2440fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org    return true;
2450fc0dea333f313a579558beb7ba498db0711780ecommit-bot@chromium.org}
246