v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lineprocessor.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <v8.h>
29 
30 #ifdef ENABLE_DEBUGGER_SUPPORT
31 #include <v8-debug.h>
32 #endif // ENABLE_DEBUGGER_SUPPORT
33 
34 #include <fcntl.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
98 };
99 
100 const char* ToCString(const v8::String::Utf8Value& value);
101 void ReportException(v8::TryCatch* handler);
102 v8::Handle<v8::String> ReadFile(const char* name);
104 
108  bool report_exceptions);
109 
110 
111 #ifdef ENABLE_DEBUGGER_SUPPORT
112 v8::Persistent<v8::Context> debug_message_context;
113 
114 void DispatchDebugMessages() {
115  // We are in some random thread. We should already have v8::Locker acquired
116  // (we requested this when registered this callback). We was called
117  // because new debug messages arrived; they may have already been processed,
118  // but we shouldn't worry about this.
119  //
120  // All we have to do is to set context and call ProcessDebugMessages.
121  //
122  // We should decide which V8 context to use here. This is important for
123  // "evaluate" command, because it must be executed some context.
124  // In our sample we have only one context, so there is nothing really to
125  // think about.
126  v8::Context::Scope scope(debug_message_context);
127 
129 }
130 #endif // ENABLE_DEBUGGER_SUPPORT
131 
132 
133 int RunMain(int argc, char* argv[]) {
134  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
135  v8::HandleScope handle_scope;
136 
137  v8::Handle<v8::String> script_source(NULL);
138  v8::Handle<v8::Value> script_name(NULL);
139  int script_param_counter = 0;
140 
141 #ifdef ENABLE_DEBUGGER_SUPPORT
142  int port_number = -1;
143  bool wait_for_connection = false;
144  bool support_callback = false;
145 #endif // ENABLE_DEBUGGER_SUPPORT
146 
147  MainCycleType cycle_type = CycleInCpp;
148 
149  for (int i = 1; i < argc; i++) {
150  const char* str = argv[i];
151  if (strcmp(str, "-f") == 0) {
152  // Ignore any -f flags for compatibility with the other stand-
153  // alone JavaScript engines.
154  continue;
155  } else if (strcmp(str, "--main-cycle-in-cpp") == 0) {
156  cycle_type = CycleInCpp;
157  } else if (strcmp(str, "--main-cycle-in-js") == 0) {
158  cycle_type = CycleInJs;
159 #ifdef ENABLE_DEBUGGER_SUPPORT
160  } else if (strcmp(str, "--callback") == 0) {
161  support_callback = true;
162  } else if (strcmp(str, "--wait-for-connection") == 0) {
163  wait_for_connection = true;
164  } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
165  port_number = atoi(argv[i + 1]); // NOLINT
166  i++;
167 #endif // ENABLE_DEBUGGER_SUPPORT
168  } else if (strncmp(str, "--", 2) == 0) {
169  printf("Warning: unknown flag %s.\nTry --help for options\n", str);
170  } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
171  script_source = v8::String::New(argv[i + 1]);
172  script_name = v8::String::New("unnamed");
173  i++;
174  script_param_counter++;
175  } else {
176  // Use argument as a name of file to load.
177  script_source = ReadFile(str);
178  script_name = v8::String::New(str);
179  if (script_source.IsEmpty()) {
180  printf("Error reading '%s'\n", str);
181  return 1;
182  }
183  script_param_counter++;
184  }
185  }
186 
187  if (script_param_counter == 0) {
188  printf("Script is not specified\n");
189  return 1;
190  }
191  if (script_param_counter != 1) {
192  printf("Only one script may be specified\n");
193  return 1;
194  }
195 
196  // Create a template for the global object.
198 
199  // Bind the global 'print' function to the C++ Print callback.
201 
202  if (cycle_type == CycleInJs) {
203  // Bind the global 'read_line' function to the C++ Print callback.
204  global->Set(v8::String::New("read_line"),
206  }
207 
208  // Create a new execution environment containing the built-in
209  // functions
210  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
211  // Enter the newly created execution environment.
212  v8::Context::Scope context_scope(context);
213 
214 #ifdef ENABLE_DEBUGGER_SUPPORT
215  debug_message_context = v8::Persistent<v8::Context>::New(context);
216 
217  v8::Locker locker;
218 
219  if (support_callback) {
220  v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
221  }
222 
223  if (port_number != -1) {
224  v8::Debug::EnableAgent("lineprocessor", port_number, wait_for_connection);
225  }
226 #endif // ENABLE_DEBUGGER_SUPPORT
227 
228  bool report_exceptions = true;
229 
230  v8::Handle<v8::Script> script;
231  {
232  // Compile script in try/catch context.
233  v8::TryCatch try_catch;
234  script = v8::Script::Compile(script_source, script_name);
235  if (script.IsEmpty()) {
236  // Print errors that happened during compilation.
237  if (report_exceptions)
238  ReportException(&try_catch);
239  return 1;
240  }
241  }
242 
243  {
244  v8::TryCatch try_catch;
245 
246  script->Run();
247  if (try_catch.HasCaught()) {
248  if (report_exceptions)
249  ReportException(&try_catch);
250  return 1;
251  }
252  }
253 
254  if (cycle_type == CycleInCpp) {
255  bool res = RunCppCycle(script, v8::Context::GetCurrent(),
256  report_exceptions);
257  return !res;
258  } else {
259  // All is already done.
260  }
261  return 0;
262 }
263 
264 
266  bool report_exceptions) {
267 #ifdef ENABLE_DEBUGGER_SUPPORT
268  v8::Locker lock;
269 #endif // ENABLE_DEBUGGER_SUPPORT
270 
271  v8::Handle<v8::String> fun_name = v8::String::New("ProcessLine");
272  v8::Handle<v8::Value> process_val =
273  v8::Context::GetCurrent()->Global()->Get(fun_name);
274 
275  // If there is no Process function, or if it is not a function,
276  // bail out
277  if (!process_val->IsFunction()) {
278  printf("Error: Script does not declare 'ProcessLine' global function.\n");
279  return 1;
280  }
281 
282  // It is a function; cast it to a Function
283  v8::Handle<v8::Function> process_fun =
284  v8::Handle<v8::Function>::Cast(process_val);
285 
286 
287  while (!feof(stdin)) {
288  v8::HandleScope handle_scope;
289 
290  v8::Handle<v8::String> input_line = ReadLine();
291  if (input_line == v8::Undefined()) {
292  continue;
293  }
294 
295  const int argc = 1;
296  v8::Handle<v8::Value> argv[argc] = { input_line };
297 
298  v8::Handle<v8::Value> result;
299  {
300  v8::TryCatch try_catch;
301  result = process_fun->Call(v8::Context::GetCurrent()->Global(),
302  argc, argv);
303  if (try_catch.HasCaught()) {
304  if (report_exceptions)
305  ReportException(&try_catch);
306  return false;
307  }
308  }
309  v8::String::Utf8Value str(result);
310  const char* cstr = ToCString(str);
311  printf("%s\n", cstr);
312  }
313 
314  return true;
315 }
316 
317 int main(int argc, char* argv[]) {
318  int result = RunMain(argc, argv);
319  v8::V8::Dispose();
320  return result;
321 }
322 
323 
324 // Extracts a C string from a V8 Utf8Value.
325 const char* ToCString(const v8::String::Utf8Value& value) {
326  return *value ? *value : "<string conversion failed>";
327 }
328 
329 
330 // Reads a file into a v8 string.
331 v8::Handle<v8::String> ReadFile(const char* name) {
332  FILE* file = fopen(name, "rb");
333  if (file == NULL) return v8::Handle<v8::String>();
334 
335  fseek(file, 0, SEEK_END);
336  int size = ftell(file);
337  rewind(file);
338 
339  char* chars = new char[size + 1];
340  chars[size] = '\0';
341  for (int i = 0; i < size;) {
342  int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
343  i += read;
344  }
345  fclose(file);
346  v8::Handle<v8::String> result = v8::String::New(chars, size);
347  delete[] chars;
348  return result;
349 }
350 
351 
352 void ReportException(v8::TryCatch* try_catch) {
353  v8::HandleScope handle_scope;
354  v8::String::Utf8Value exception(try_catch->Exception());
355  const char* exception_string = ToCString(exception);
356  v8::Handle<v8::Message> message = try_catch->Message();
357  if (message.IsEmpty()) {
358  // V8 didn't provide any extra information about this error; just
359  // print the exception.
360  printf("%s\n", exception_string);
361  } else {
362  // Print (filename):(line number): (message).
363  v8::String::Utf8Value filename(message->GetScriptResourceName());
364  const char* filename_string = ToCString(filename);
365  int linenum = message->GetLineNumber();
366  printf("%s:%i: %s\n", filename_string, linenum, exception_string);
367  // Print line of source code.
368  v8::String::Utf8Value sourceline(message->GetSourceLine());
369  const char* sourceline_string = ToCString(sourceline);
370  printf("%s\n", sourceline_string);
371  // Print wavy underline (GetUnderline is deprecated).
372  int start = message->GetStartColumn();
373  for (int i = 0; i < start; i++) {
374  printf(" ");
375  }
376  int end = message->GetEndColumn();
377  for (int i = start; i < end; i++) {
378  printf("^");
379  }
380  printf("\n");
381  }
382 }
383 
384 
385 // The callback that is invoked by v8 whenever the JavaScript 'print'
386 // function is called. Prints its arguments on stdout separated by
387 // spaces and ending with a newline.
389  bool first = true;
390  for (int i = 0; i < args.Length(); i++) {
391  v8::HandleScope handle_scope;
392  if (first) {
393  first = false;
394  } else {
395  printf(" ");
396  }
397  v8::String::Utf8Value str(args[i]);
398  const char* cstr = ToCString(str);
399  printf("%s", cstr);
400  }
401  printf("\n");
402  fflush(stdout);
403  return v8::Undefined();
404 }
405 
406 
407 // The callback that is invoked by v8 whenever the JavaScript 'read_line'
408 // function is called. Reads a string from standard input and returns.
410  if (args.Length() > 0) {
411  return v8::ThrowException(v8::String::New("Unexpected arguments"));
412  }
413  return ReadLine();
414 }
415 
417  const int kBufferSize = 1024 + 1;
418  char buffer[kBufferSize];
419 
420  char* res;
421  {
422 #ifdef ENABLE_DEBUGGER_SUPPORT
423  v8::Unlocker unlocker;
424 #endif // ENABLE_DEBUGGER_SUPPORT
425  res = fgets(buffer, kBufferSize, stdin);
426  }
427  if (res == NULL) {
430  }
431  // Remove newline char
432  for (char* pos = buffer; *pos != '\0'; pos++) {
433  if (*pos == '\n') {
434  *pos = '\0';
435  break;
436  }
437  }
438  return v8::String::New(buffer);
439 }
static Local< Context > GetCurrent()
Definition: api.cc:4545
v8::Handle< v8::String > ReadFile(const char *name)
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1568
MainCycleType
static Local< FunctionTemplate > New(InvocationCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >())
Definition: api.cc:951
const char * ToCString(const v8::String::Utf8Value &value)
Local< Value > Exception() const
Definition: api.cc:1720
bool HasCaught() const
Definition: api.cc:1703
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
static Handle< T > Cast(Handle< S > that)
Definition: v8.h:244
V8EXPORT Local< Value > Call(Handle< Object > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3652
v8::Handle< v8::Value > Print(const v8::Arguments &args)
v8::Handle< v8::String > ReadLine()
void Set(Handle< String > name, Handle< Data > value, PropertyAttribute attributes=None)
Definition: api.cc:902
static bool Dispose()
Definition: api.cc:4303
Handle< Value > GetScriptResourceName() const
Definition: api.cc:1793
int GetEndColumn() const
Definition: api.cc:1928
static Local< ObjectTemplate > New()
Definition: api.cc:1253
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
int Length() const
Definition: v8.h:4318
static Persistent< T > New(Handle< T > that)
Definition: v8.h:4206
static String * Cast(v8::Value *obj)
Definition: v8.h:4417
Definition: v8.h:105
static bool EnableAgent(const char *name, int port, bool wait_for_connection=false)
int GetLineNumber() const
Definition: api.cc:1873
V8EXPORT bool IsFunction() const
Definition: api.cc:2155
bool RunCppCycle(v8::Handle< v8::Script > script, v8::Local< v8::Context > context, bool report_exceptions)
static void SetDebugMessageDispatchHandler(DebugMessageDispatchHandler handler, bool provide_locker=false)
void ReportException(v8::TryCatch *handler)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
int RunMain(int argc, char *argv[])
Handle< Primitive > V8EXPORT Undefined()
Definition: api.cc:549
bool IsEmpty() const
Definition: v8.h:209
Local< Value > Run()
Definition: api.cc:1598
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
static void SetFlagsFromCommandLine(int *argc, char **argv, bool remove_flags)
Definition: api.cc:481
int GetStartColumn() const
Definition: api.cc:1910
int main(int argc, char *argv[])
Handle< Value > V8EXPORT ThrowException(Handle< Value > exception)
Definition: api.cc:486
static void ProcessDebugMessages()
Definition: v8.h:106
Local< v8::Message > Message() const
Definition: api.cc:1750
Local< String > GetSourceLine() const
Definition: api.cc:1948