Author: [email protected]
Date: Mon Mar 30 23:51:25 2009
New Revision: 1644

Modified:
    branches/bleeding_edge/include/v8.h
    branches/bleeding_edge/src/d8-posix.cc
    branches/bleeding_edge/src/d8-windows.cc
    branches/bleeding_edge/src/d8.cc
    branches/bleeding_edge/src/d8.h

Log:
Add os.chdir and os.setenv to d8.  Move system() to os.system().
Protect os.chdir, os.setenv, os.system against string conversion
failures.  Add comment about the issue to include/v8.h.
Review URL: http://codereview.chromium.org/57005

Modified: branches/bleeding_edge/include/v8.h
==============================================================================
--- branches/bleeding_edge/include/v8.h (original)
+++ branches/bleeding_edge/include/v8.h Mon Mar 30 23:51:25 2009
@@ -883,7 +883,10 @@

    /**
     * Converts an object to a utf8-encoded character array.  Useful if
-   * you want to print the object.
+   * you want to print the object.  If conversion to a string fails
+   * (eg. due to an exception in the toString() method of the object)
+   * then the length() method returns 0 and the * operator returns
+   * NULL.
     */
    class V8EXPORT Utf8Value {
     public:
@@ -903,6 +906,9 @@
    /**
     * Converts an object to an ascii string.
     * Useful if you want to print the object.
+   * If conversion to a string fails (eg. due to an exception in the  
toString()
+   * method of the object) then the length() method returns 0 and the *  
operator
+   * returns NULL.
     */
    class V8EXPORT AsciiValue {
     public:
@@ -921,6 +927,9 @@

    /**
     * Converts an object to a two-byte string.
+   * If conversion to a string fails (eg. due to an exception in the  
toString()
+   * method of the object) then the length() method returns 0 and the *  
operator
+   * returns NULL.
     */
    class V8EXPORT Value {
     public:

Modified: branches/bleeding_edge/src/d8-posix.cc
==============================================================================
--- branches/bleeding_edge/src/d8-posix.cc      (original)
+++ branches/bleeding_edge/src/d8-posix.cc      Mon Mar 30 23:51:25 2009
@@ -184,9 +184,18 @@
  // scope.
  class ExecArgs {
   public:
-  ExecArgs(Handle<Value> arg0, Handle<Array> command_args) {
+  ExecArgs() {
+    exec_args_[0] = NULL;
+  }
+  bool Init(Handle<Value> arg0, Handle<Array> command_args) {
      String::Utf8Value prog(arg0);
-    int len = prog.length() + 1;
+    if (*prog == NULL) {
+      const char* message =
+          "os.system(): String conversion of program name failed";
+      ThrowException(String::New(message));
+      return false;
+    }
+    int len = prog.length() + 3;
      char* c_arg = new char[len];
      snprintf(c_arg, len, "%s", *prog);
      exec_args_[0] = c_arg;
@@ -194,12 +203,20 @@
      for (unsigned j = 0; j < command_args->Length(); i++, j++) {
        Handle<Value> arg(command_args->Get(Integer::New(j)));
        String::Utf8Value utf8_arg(arg);
+      if (*utf8_arg == NULL) {
+        exec_args_[i] = NULL;  // Consistent state for destructor.
+        const char* message =
+            "os.system(): String conversion of argument failed.";
+        ThrowException(String::New(message));
+        return false;
+      }
        int len = utf8_arg.length() + 1;
        char* c_arg = new char[len];
        snprintf(c_arg, len, "%s", *utf8_arg);
        exec_args_[i] = c_arg;
      }
      exec_args_[i] = NULL;
+    return true;
    }
    ~ExecArgs() {
      for (unsigned i = 0; i < kMaxArgs; i++) {
@@ -454,7 +471,10 @@
    struct timeval start_time;
    gettimeofday(&start_time, NULL);

-  ExecArgs exec_args(args[0], command_args);
+  ExecArgs exec_args;
+  if (!exec_args.Init(args[0], command_args)) {
+    return v8::Undefined();
+  }
    int exec_error_fds[2];
    int stdout_fds[2];

@@ -498,6 +518,23 @@
    }

    return scope.Close(accumulator);
+}
+
+
+Handle<Value> Shell::ChangeDirectory(const Arguments& args) {
+  if (args.Length() != 1) {
+    const char* message = "chdir() takes one argument";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value directory(args[0]);
+  if (*directory == NULL) {
+    const char* message = "os.chdir(): String conversion of argument  
failed.";
+    return ThrowException(String::New(message));
+  }
+  if (chdir(*directory) != 0) {
+    return ThrowException(String::New(strerror(errno)));
+  }
+  return v8::Undefined();
  }



Modified: branches/bleeding_edge/src/d8-windows.cc
==============================================================================
--- branches/bleeding_edge/src/d8-windows.cc    (original)
+++ branches/bleeding_edge/src/d8-windows.cc    Mon Mar 30 23:51:25 2009
@@ -42,4 +42,11 @@
  }


+Handle<Value> Shell::ChangeDirectory(const Arguments& args) {
+  Handle<String> error_message =
+      String::New("chdir() is not yet supported on your OS");
+  return ThrowException(error_message);
+}
+
+
  }  // namespace v8

Modified: branches/bleeding_edge/src/d8.cc
==============================================================================
--- branches/bleeding_edge/src/d8.cc    (original)
+++ branches/bleeding_edge/src/d8.cc    Mon Mar 30 23:51:25 2009
@@ -163,6 +163,28 @@
  }


+Handle<Value> Shell::SetEnvironment(const Arguments& args) {
+  if (args.Length() != 2) {
+    const char* message = "setenv() takes two arguments";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value var(args[0]);
+  String::Utf8Value value(args[1]);
+  if (*var == NULL) {
+    const char* message =
+        "os.setenv(): String conversion of variable name failed.";
+    return ThrowException(String::New(message));
+  }
+  if (*value == NULL) {
+    const char* message =
+        "os.setenv(): String conversion of variable contents failed.";
+    return ThrowException(String::New(message));
+  }
+  setenv(*var, *value, 1);
+  return v8::Undefined();
+}
+
+
  Handle<Value> Shell::Load(const Arguments& args) {
    for (int i = 0; i < args.Length(); i++) {
      HandleScope handle_scope;
@@ -342,7 +364,12 @@
    global_template->Set(String::New("load"), FunctionTemplate::New(Load));
    global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
    global_template->Set(String::New("version"),  
FunctionTemplate::New(Version));
-  global_template->Set(String::New("system"),  
FunctionTemplate::New(System));
+
+  Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
+  os_templ->Set(String::New("system"), FunctionTemplate::New(System));
+  os_templ->Set(String::New("chdir"),  
FunctionTemplate::New(ChangeDirectory));
+  os_templ->Set(String::New("setenv"),  
FunctionTemplate::New(SetEnvironment));
+  global_template->Set(String::New("os"), os_templ);

    utility_context_ = Context::New(NULL, global_template);
    utility_context_->SetSecurityToken(Undefined());

Modified: branches/bleeding_edge/src/d8.h
==============================================================================
--- branches/bleeding_edge/src/d8.h     (original)
+++ branches/bleeding_edge/src/d8.h     Mon Mar 30 23:51:25 2009
@@ -130,9 +130,12 @@
    static Handle<Value> Quit(const Arguments& args);
    static Handle<Value> Version(const Arguments& args);
    static Handle<Value> Load(const Arguments& args);
-  // system("program_name", ["arg1", "arg2", ...], timeout1, timeout2)  
will run
-  // the command, passing the arguments to the program.  The standard  
output of
-  // the program will be picked up and returned as a multiline string.  If
+  // The OS object on the global object contains methods for performing
+  // operating system calls:
+  //
+  // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2)  
will
+  // run the command, passing the arguments to the program.  The standard  
output
+  // of the program will be picked up and returned as a multiline string.   
If
    // timeout1 is present then it should be a number.  -1 indicates no  
timeout
    // and a positive number is used as a timeout in milliseconds that  
limits the
    // time spent waiting between receiving output characters from the  
program.
@@ -140,7 +143,16 @@
    // milliseconds on the total running time of the program.  Exceptions are
    // thrown on timeouts or other errors or if the exit status of the  
program
    // indicates an error.
+  //
+  // os.chdir(dir) changes directory to the given directory.  Throws an
+  // exception/ on error.
+  //
+  // os.setenv(variable, value) sets an environment variable.  Repeated  
calls to
+  // this method leak memory due to the API of setenv in the standard C  
library.
+  static Handle<Value> OSObject(const Arguments& args);
    static Handle<Value> System(const Arguments& args);
+  static Handle<Value> ChangeDirectory(const Arguments& args);
+  static Handle<Value> SetEnvironment(const Arguments& args);

    static Handle<Context> utility_context() { return utility_context_; }


--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to