lineprocessor.cc revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
1e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Copyright 2009 the V8 project authors. All rights reserved. 2e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Redistribution and use in source and binary forms, with or without 3e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// modification, are permitted provided that the following conditions are 4e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// met: 5e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// 6e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// * Redistributions of source code must retain the above copyright 7e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// notice, this list of conditions and the following disclaimer. 8e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// * Redistributions in binary form must reproduce the above 9e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// copyright notice, this list of conditions and the following 10e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// disclaimer in the documentation and/or other materials provided 11e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// with the distribution. 12e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// * Neither the name of Google Inc. nor the names of its 13e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// contributors may be used to endorse or promote products derived 14e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// from this software without specific prior written permission. 15e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// 16e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 28e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <v8.h> 29e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <v8-debug.h> 30e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <fcntl.h> 31e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <string.h> 32e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <stdio.h> 33e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#include <stdlib.h> 34e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke/** 36e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * This sample program should demonstrate certain aspects of debugging 37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * standalone V8-based application. 38e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 39e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * The program reads input stream, processes it line by line and print 40e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * the result to output. The actual processing is done by custom JavaScript 41e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * script. The script is specified with command line parameters. 42e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * The main cycle of the program will sequentially read lines from standard 44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * input, process them and print to standard output until input closes. 45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * There are 2 possible configuration in regard to main cycle. 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 1. The main cycle is on C++ side. Program should be run with 48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * --main-cycle-in-cpp option. Script must declare a function named 49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * "ProcessLine". The main cycle in C++ reads lines and calls this function 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * for processing every time. This is a sample script: 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkefunction ProcessLine(input_line) { 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return ">>>" + input_line + "<<<"; 54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 2. The main cycle is in JavaScript. Program should be run with 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * --main-cycle-in-js option. Script gets run one time at all and gets 59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * API of 2 global functions: "read_line" and "print". It should read input 60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * and print converted lines to output itself. This a sample script: 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkewhile (true) { 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke var line = read_line(); 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!line) { 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 67e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke var res = line + " | " + line; 68e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke print(res); 69e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 70e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 71e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 72e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * When run with "-p" argument, the program starts V8 Debugger Agent and 73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * allows remote debugger to attach and debug JavaScript code. 74e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 75e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * Interesting aspects: 76e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 1. Wait for remote debugger to attach 77e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * Normally the program compiles custom script and immediately runs it. 78e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * If programmer needs to debug script from the very beginning, he should 79e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * run this sample program with "--wait-for-connection" command line parameter. 80e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * This way V8 will suspend on the first statement and wait for 81e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * debugger to attach. 82e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 83e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * 2. Unresponsive V8 84e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * V8 Debugger Agent holds a connection with remote debugger, but it does 85e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * respond only when V8 is running some script. In particular, when this program 86e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * is waiting for input, all requests from debugger get deferred until V8 87e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * is called again. See how "--callback" command-line parameter in this sample 88e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * fixes this issue. 89e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke */ 90e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 91e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeenum MainCycleType { 92e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CycleInCpp, 93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CycleInJs 94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 95e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeconst char* ToCString(const v8::String::Utf8Value& value); 97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid ReportException(v8::TryCatch* handler); 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::String> ReadFile(const char* name); 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::String> ReadLine(); 100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::Value> Print(const v8::Arguments& args); 102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::Value> ReadLine(const v8::Arguments& args); 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool RunCppCycle(v8::Handle<v8::Script> script, v8::Local<v8::Context> context, 104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool report_exceptions); 105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Persistent<v8::Context> debug_message_context; 107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid DispatchDebugMessages() { 110e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We are in some random thread. We should already have v8::Locker acquired 111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // (we requested this when registered this callback). We was called 112e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // because new debug messages arrived; they may have already been processed, 113e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // but we shouldn't worry about this. 114e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 115e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // All we have to do is to set context and call ProcessDebugMessages. 116e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // We should decide which V8 context to use here. This is important for 118e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // "evaluate" command, because it must be executed some context. 119e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In our sample we have only one context, so there is nothing really to 120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // think about. 121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Context::Scope scope(debug_message_context); 122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Debug::ProcessDebugMessages(); 124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeint RunMain(int argc, char* argv[]) { 128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::HandleScope handle_scope; 130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::String> script_source(NULL); 132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Value> script_name(NULL); 133e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int script_param_counter = 0; 134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int port_number = -1; 136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool wait_for_connection = false; 137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool support_callback = true; 138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke MainCycleType cycle_type = CycleInCpp; 139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (int i = 1; i < argc; i++) { 141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* str = argv[i]; 142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (strcmp(str, "-f") == 0) { 143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Ignore any -f flags for compatibility with the other stand- 144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // alone JavaScript engines. 145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke continue; 146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "--callback") == 0) { 147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // TODO(548): implement this. 148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Error: debugger agent callback is not supported yet.\n"); 149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "--wait-for-connection") == 0) { 151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke wait_for_connection = true; 152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "--main-cycle-in-cpp") == 0) { 153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke cycle_type = CycleInCpp; 154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "--main-cycle-in-js") == 0) { 155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke cycle_type = CycleInJs; 156e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "-p") == 0 && i + 1 < argc) { 157e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke port_number = atoi(argv[i + 1]); 158e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke i++; 159e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strncmp(str, "--", 2) == 0) { 160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Warning: unknown flag %s.\nTry --help for options\n", str); 161e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { 162e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_source = v8::String::New(argv[i + 1]); 163e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_name = v8::String::New("unnamed"); 164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke i++; 165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_param_counter++; 166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use argument as a name of file to load. 168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_source = ReadFile(str); 169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_name = v8::String::New(str); 170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (script_source.IsEmpty()) { 171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Error reading '%s'\n", str); 172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script_param_counter++; 175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (script_param_counter == 0) { 179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Script is not specified\n"); 180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (script_param_counter != 1) { 183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Only one script may be specified\n"); 184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Create a template for the global object. 188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); 189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Bind the global 'print' function to the C++ Print callback. 191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); 192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (cycle_type == CycleInJs) { 194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Bind the global 'read_line' function to the C++ Print callback. 195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke global->Set(v8::String::New("read_line"), 196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::FunctionTemplate::New(ReadLine)); 197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Create a new execution environment containing the built-in 200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // functions 201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Context> context = v8::Context::New(NULL, global); 202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke debug_message_context = v8::Persistent<v8::Context>::New(context); 203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Enter the newly created execution environment. 206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Context::Scope context_scope(context); 207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Locker locker; 209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (support_callback) { 211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true); 212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (port_number != -1) { 215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* auto_break_param = "--debugger_auto_break"; 216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::V8::SetFlagsFromString(auto_break_param, strlen(auto_break_param)); 217e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Debug::EnableAgent("lineprocessor", port_number, wait_for_connection); 218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool report_exceptions = true; 221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Script> script; 223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { 224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compile script in try/catch context. 225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::TryCatch try_catch; 226e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script = v8::Script::Compile(script_source, script_name); 227e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (script.IsEmpty()) { 228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Print errors that happened during compilation. 229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (report_exceptions) 230e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ReportException(&try_catch); 231e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { 236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::TryCatch try_catch; 237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke script->Run(); 239e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (try_catch.HasCaught()) { 240e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (report_exceptions) 241e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ReportException(&try_catch); 242e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 243e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (cycle_type == CycleInCpp) { 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool res = RunCppCycle(script, v8::Context::GetCurrent(), 248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke report_exceptions); 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return !res; 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // All is already done. 252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 0; 254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool RunCppCycle(v8::Handle<v8::Script> script, v8::Local<v8::Context> context, 258e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool report_exceptions) { 259e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Locker lock; 260e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 261e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::String> fun_name = v8::String::New("ProcessLine"); 262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Value> process_val = 263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Context::GetCurrent()->Global()->Get(fun_name); 264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If there is no Process function, or if it is not a function, 266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // bail out 267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!process_val->IsFunction()) { 268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("Error: Script does not declare 'ProcessLine' global function.\n"); 269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return 1; 270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // It is a function; cast it to a Function 273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Function> process_fun = 274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Function>::Cast(process_val); 275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke while (!feof(stdin)) { 278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::HandleScope handle_scope; 279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::String> input_line = ReadLine(); 281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (input_line == v8::Undefined()) { 282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke continue; 283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int argc = 1; 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Value> argv[argc] = { input_line }; 287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Value> result; 289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { 290e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::TryCatch try_catch; 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result = process_fun->Call(v8::Context::GetCurrent()->Global(), 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke argc, argv); 293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (try_catch.HasCaught()) { 294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (report_exceptions) 295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ReportException(&try_catch); 296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return false; 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::String::Utf8Value str(result); 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* cstr = ToCString(str); 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%s\n", cstr); 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeint main(int argc, char* argv[]) { 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int result = RunMain(argc, argv); 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::V8::Dispose(); 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return result; 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Extracts a C string from a V8 Utf8Value. 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeconst char* ToCString(const v8::String::Utf8Value& value) { 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return *value ? *value : "<string conversion failed>"; 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Reads a file into a v8 string. 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::String> ReadFile(const char* name) { 322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke FILE* file = fopen(name, "rb"); 323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (file == NULL) return v8::Handle<v8::String>(); 324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke fseek(file, 0, SEEK_END); 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int size = ftell(file); 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke rewind(file); 328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke char* chars = new char[size + 1]; 330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke chars[size] = '\0'; 331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (int i = 0; i < size;) { 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int read = fread(&chars[i], 1, size - i, file); 333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke i += read; 334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke fclose(file); 336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::String> result = v8::String::New(chars, size); 337e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke delete[] chars; 338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return result; 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid ReportException(v8::TryCatch* try_catch) { 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::HandleScope handle_scope; 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::String::Utf8Value exception(try_catch->Exception()); 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* exception_string = ToCString(exception); 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Message> message = try_catch->Message(); 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (message.IsEmpty()) { 348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // V8 didn't provide any extra information about this error; just 349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // print the exception. 350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%s\n", exception_string); 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Print (filename):(line number): (message). 353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::String::Utf8Value filename(message->GetScriptResourceName()); 354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* filename_string = ToCString(filename); 355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int linenum = message->GetLineNumber(); 356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%s:%i: %s\n", filename_string, linenum, exception_string); 357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Print line of source code. 358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::String::Utf8Value sourceline(message->GetSourceLine()); 359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* sourceline_string = ToCString(sourceline); 360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%s\n", sourceline_string); 361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Print wavy underline (GetUnderline is deprecated). 362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int start = message->GetStartColumn(); 363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (int i = 0; i < start; i++) { 364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf(" "); 365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int end = message->GetEndColumn(); 367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (int i = start; i < end; i++) { 368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("^"); 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("\n"); 371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// The callback that is invoked by v8 whenever the JavaScript 'print' 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// function is called. Prints its arguments on stdout separated by 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// spaces and ending with a newline. 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::Value> Print(const v8::Arguments& args) { 379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool first = true; 380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (int i = 0; i < args.Length(); i++) { 381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::HandleScope handle_scope; 382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (first) { 383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke first = false; 384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf(" "); 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::String::Utf8Value str(args[i]); 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* cstr = ToCString(str); 389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%s", cstr); 390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("\n"); 392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke fflush(stdout); 393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return v8::Undefined(); 394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// The callback that is invoked by v8 whenever the JavaScript 'read_line' 398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// function is called. Reads a string from standard input and returns. 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::Value> ReadLine(const v8::Arguments& args) { 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (args.Length() > 0) { 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return v8::ThrowException(v8::String::New("Unexpected arguments")); 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return ReadLine(); 404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkev8::Handle<v8::String> ReadLine() { 407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const int kBufferSize = 1024 + 1; 408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke char buffer[kBufferSize]; 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke char* res; 411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke { 412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Unlocker unlocker; 413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke res = fgets(buffer, buffer_size, stdin); 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (res == NULL) { 416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke v8::Handle<v8::Primitive> t = v8::Undefined(); 417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return reinterpret_cast<v8::Handle<v8::String>&>(t); 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // remove newline char 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke for (char* pos = buffer; *pos != '\0'; pos++) { 421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (*pos == '\n') { 422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *pos = '\0'; 423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return v8::String::New(buffer); 427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 428