Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Remove unnecessary files.

  • Loading branch information...
commit afc509c7e4965aa27b8fab247f16d116b1844be5 1 parent 72b77c2
Ariya Hidayat ariya authored
367 v8/src/d8-debug.cc
View
@@ -1,367 +0,0 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "d8.h"
-#include "d8-debug.h"
-#include "platform.h"
-#include "debug-agent.h"
-
-
-namespace v8 {
-
-static bool was_running = true;
-
-void PrintPrompt(bool is_running) {
- const char* prompt = is_running? "> " : "dbg> ";
- was_running = is_running;
- printf("%s", prompt);
- fflush(stdout);
-}
-
-
-void PrintPrompt() {
- PrintPrompt(was_running);
-}
-
-
-void HandleDebugEvent(DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- Handle<Value> data) {
- HandleScope scope;
-
- // Check for handled event.
- if (event != Break && event != Exception && event != AfterCompile) {
- return;
- }
-
- TryCatch try_catch;
-
- // Get the toJSONProtocol function on the event and get the JSON format.
- Local<String> to_json_fun_name = String::New("toJSONProtocol");
- Local<Function> to_json_fun =
- Function::Cast(*event_data->Get(to_json_fun_name));
- Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- return;
- }
-
- // Print the event details.
- Handle<Object> details =
- Shell::DebugMessageDetails(Handle<String>::Cast(event_json));
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- return;
- }
- String::Utf8Value str(details->Get(String::New("text")));
- if (str.length() == 0) {
- // Empty string is used to signal not to process this event.
- return;
- }
- printf("%s\n", *str);
-
- // Get the debug command processor.
- Local<String> fun_name = String::New("debugCommandProcessor");
- Local<Function> fun = Function::Cast(*exec_state->Get(fun_name));
- Local<Object> cmd_processor =
- Object::Cast(*fun->Call(exec_state, 0, NULL));
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- return;
- }
-
- static const int kBufferSize = 256;
- bool running = false;
- while (!running) {
- char command[kBufferSize];
- PrintPrompt(running);
- char* str = fgets(command, kBufferSize, stdin);
- if (str == NULL) break;
-
- // Ignore empty commands.
- if (strlen(command) == 0) continue;
-
- TryCatch try_catch;
-
- // Convert the debugger command to a JSON debugger request.
- Handle<Value> request =
- Shell::DebugCommandToJSONRequest(String::New(command));
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- continue;
- }
-
- // If undefined is returned the command was handled internally and there is
- // no JSON to send.
- if (request->IsUndefined()) {
- continue;
- }
-
- Handle<String> fun_name;
- Handle<Function> fun;
- // All the functions used below take one argument.
- static const int kArgc = 1;
- Handle<Value> args[kArgc];
-
- // Invoke the JavaScript to convert the debug command line to a JSON
- // request, invoke the JSON request and convert the JSON respose to a text
- // representation.
- fun_name = String::New("processDebugRequest");
- fun = Handle<Function>::Cast(cmd_processor->Get(fun_name));
- args[0] = request;
- Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- continue;
- }
- Handle<String> response = Handle<String>::Cast(response_val);
-
- // Convert the debugger response into text details and the running state.
- Handle<Object> response_details = Shell::DebugMessageDetails(response);
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- continue;
- }
- String::Utf8Value text_str(response_details->Get(String::New("text")));
- if (text_str.length() > 0) {
- printf("%s\n", *text_str);
- }
- running =
- response_details->Get(String::New("running"))->ToBoolean()->Value();
- }
-}
-
-
-void RunRemoteDebugger(int port) {
- RemoteDebugger debugger(i::Isolate::Current(), port);
- debugger.Run();
-}
-
-
-void RemoteDebugger::Run() {
- bool ok;
-
- // Make sure that socket support is initialized.
- ok = i::Socket::Setup();
- if (!ok) {
- printf("Unable to initialize socket support %d\n", i::Socket::LastError());
- return;
- }
-
- // Connect to the debugger agent.
- conn_ = i::OS::CreateSocket();
- static const int kPortStrSize = 6;
- char port_str[kPortStrSize];
- i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
- ok = conn_->Connect("localhost", port_str);
- if (!ok) {
- printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
- return;
- }
-
- // Start the receiver thread.
- ReceiverThread receiver(isolate_, this);
- receiver.Start();
-
- // Start the keyboard thread.
- KeyboardThread keyboard(isolate_, this);
- keyboard.Start();
- PrintPrompt();
-
- // Process events received from debugged VM and from the keyboard.
- bool terminate = false;
- while (!terminate) {
- event_available_->Wait();
- RemoteDebuggerEvent* event = GetEvent();
- switch (event->type()) {
- case RemoteDebuggerEvent::kMessage:
- HandleMessageReceived(event->data());
- break;
- case RemoteDebuggerEvent::kKeyboard:
- HandleKeyboardCommand(event->data());
- break;
- case RemoteDebuggerEvent::kDisconnect:
- terminate = true;
- break;
-
- default:
- UNREACHABLE();
- }
- delete event;
- }
-
- // Wait for the receiver thread to end.
- receiver.Join();
-}
-
-
-void RemoteDebugger::MessageReceived(i::SmartPointer<char> message) {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
- AddEvent(event);
-}
-
-
-void RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
- AddEvent(event);
-}
-
-
-void RemoteDebugger::ConnectionClosed() {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
- i::SmartPointer<char>());
- AddEvent(event);
-}
-
-
-void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
- i::ScopedLock lock(event_access_);
- if (head_ == NULL) {
- ASSERT(tail_ == NULL);
- head_ = event;
- tail_ = event;
- } else {
- ASSERT(tail_ != NULL);
- tail_->set_next(event);
- tail_ = event;
- }
- event_available_->Signal();
-}
-
-
-RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
- i::ScopedLock lock(event_access_);
- ASSERT(head_ != NULL);
- RemoteDebuggerEvent* result = head_;
- head_ = head_->next();
- if (head_ == NULL) {
- ASSERT(tail_ == result);
- tail_ = NULL;
- }
- return result;
-}
-
-
-void RemoteDebugger::HandleMessageReceived(char* message) {
- HandleScope scope;
-
- // Print the event details.
- TryCatch try_catch;
- Handle<Object> details =
- Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
- if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
- PrintPrompt();
- return;
- }
- String::Utf8Value str(details->Get(String::New("text")));
- if (str.length() == 0) {
- // Empty string is used to signal not to process this event.
- return;
- }
- if (*str != NULL) {
- printf("%s\n", *str);
- } else {
- printf("???\n");
- }
-
- bool is_running = details->Get(String::New("running"))->ToBoolean()->Value();
- PrintPrompt(is_running);
-}
-
-
-void RemoteDebugger::HandleKeyboardCommand(char* command) {
- HandleScope scope;
-
- // Convert the debugger command to a JSON debugger request.
- TryCatch try_catch;
- Handle<Value> request =
- Shell::DebugCommandToJSONRequest(String::New(command));
- if (try_catch.HasCaught()) {
- v8::String::Utf8Value exception(try_catch.Exception());
- const char* exception_string = Shell::ToCString(exception);
- printf("%s\n", exception_string);
- PrintPrompt();
- return;
- }
-
- // If undefined is returned the command was handled internally and there is
- // no JSON to send.
- if (request->IsUndefined()) {
- PrintPrompt();
- return;
- }
-
- // Send the JSON debugger request.
- i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
-}
-
-
-void ReceiverThread::Run() {
- // Receive the connect message (with empty body).
- i::SmartPointer<char> message =
- i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
- ASSERT(*message == NULL);
-
- while (true) {
- // Receive a message.
- i::SmartPointer<char> message =
- i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
- if (*message == NULL) {
- remote_debugger_->ConnectionClosed();
- return;
- }
-
- // Pass the message to the main thread.
- remote_debugger_->MessageReceived(message);
- }
-}
-
-
-void KeyboardThread::Run() {
- static const int kBufferSize = 256;
- while (true) {
- // read keyboard input.
- char command[kBufferSize];
- char* str = fgets(command, kBufferSize, stdin);
- if (str == NULL) {
- break;
- }
-
- // Pass the keyboard command to the main thread.
- remote_debugger_->KeyboardCommand(
- i::SmartPointer<char>(i::StrDup(command)));
- }
-}
-
-
-} // namespace v8
158 v8/src/d8-debug.h
View
@@ -1,158 +0,0 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_D8_DEBUG_H_
-#define V8_D8_DEBUG_H_
-
-
-#include "d8.h"
-#include "debug.h"
-
-
-namespace v8 {
-
-
-void HandleDebugEvent(DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- Handle<Value> data);
-
-// Start the remove debugger connecting to a V8 debugger agent on the specified
-// port.
-void RunRemoteDebugger(int port);
-
-// Forward declerations.
-class RemoteDebuggerEvent;
-class ReceiverThread;
-
-
-// Remote debugging class.
-class RemoteDebugger {
- public:
- RemoteDebugger(i::Isolate* isolate, int port)
- : port_(port),
- event_access_(i::OS::CreateMutex()),
- event_available_(i::OS::CreateSemaphore(0)),
- head_(NULL), tail_(NULL), isolate_(isolate) {}
- void Run();
-
- // Handle events from the subordinate threads.
- void MessageReceived(i::SmartPointer<char> message);
- void KeyboardCommand(i::SmartPointer<char> command);
- void ConnectionClosed();
-
- private:
- // Add new debugger event to the list.
- void AddEvent(RemoteDebuggerEvent* event);
- // Read next debugger event from the list.
- RemoteDebuggerEvent* GetEvent();
-
- // Handle a message from the debugged V8.
- void HandleMessageReceived(char* message);
- // Handle a keyboard command.
- void HandleKeyboardCommand(char* command);
-
- // Get connection to agent in debugged V8.
- i::Socket* conn() { return conn_; }
-
- int port_; // Port used to connect to debugger V8.
- i::Socket* conn_; // Connection to debugger agent in debugged V8.
-
- // Linked list of events from debugged V8 and from keyboard input. Access to
- // the list is guarded by a mutex and a semaphore signals new items in the
- // list.
- i::Mutex* event_access_;
- i::Semaphore* event_available_;
- RemoteDebuggerEvent* head_;
- RemoteDebuggerEvent* tail_;
- i::Isolate* isolate_;
-
- friend class ReceiverThread;
-};
-
-
-// Thread reading from debugged V8 instance.
-class ReceiverThread: public i::Thread {
- public:
- ReceiverThread(i::Isolate* isolate, RemoteDebugger* remote_debugger)
- : Thread(isolate, "d8:ReceiverThrd"),
- remote_debugger_(remote_debugger) {}
- ~ReceiverThread() {}
-
- void Run();
-
- private:
- RemoteDebugger* remote_debugger_;
-};
-
-
-// Thread reading keyboard input.
-class KeyboardThread: public i::Thread {
- public:
- explicit KeyboardThread(i::Isolate* isolate, RemoteDebugger* remote_debugger)
- : Thread(isolate, "d8:KeyboardThrd"),
- remote_debugger_(remote_debugger) {}
- ~KeyboardThread() {}
-
- void Run();
-
- private:
- RemoteDebugger* remote_debugger_;
-};
-
-
-// Events processed by the main deubgger thread.
-class RemoteDebuggerEvent {
- public:
- RemoteDebuggerEvent(int type, i::SmartPointer<char> data)
- : type_(type), data_(data), next_(NULL) {
- ASSERT(type == kMessage || type == kKeyboard || type == kDisconnect);
- }
-
- static const int kMessage = 1;
- static const int kKeyboard = 2;
- static const int kDisconnect = 3;
-
- int type() { return type_; }
- char* data() { return *data_; }
-
- private:
- void set_next(RemoteDebuggerEvent* event) { next_ = event; }
- RemoteDebuggerEvent* next() { return next_; }
-
- int type_;
- i::SmartPointer<char> data_;
- RemoteDebuggerEvent* next_;
-
- friend class RemoteDebugger;
-};
-
-
-} // namespace v8
-
-
-#endif // V8_D8_DEBUG_H_
695 v8/src/d8-posix.cc
View
@@ -1,695 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-
-#include "d8.h"
-#include "d8-debug.h"
-#include "debug.h"
-
-
-namespace v8 {
-
-
-// If the buffer ends in the middle of a UTF-8 sequence then we return
-// the length of the string up to but not including the incomplete UTF-8
-// sequence. If the buffer ends with a valid UTF-8 sequence then we
-// return the whole buffer.
-static int LengthWithoutIncompleteUtf8(char* buffer, int len) {
- int answer = len;
- // 1-byte encoding.
- static const int kUtf8SingleByteMask = 0x80;
- static const int kUtf8SingleByteValue = 0x00;
- // 2-byte encoding.
- static const int kUtf8TwoByteMask = 0xe0;
- static const int kUtf8TwoByteValue = 0xc0;
- // 3-byte encoding.
- static const int kUtf8ThreeByteMask = 0xf0;
- static const int kUtf8ThreeByteValue = 0xe0;
- // 4-byte encoding.
- static const int kUtf8FourByteMask = 0xf8;
- static const int kUtf8FourByteValue = 0xf0;
- // Subsequent bytes of a multi-byte encoding.
- static const int kMultiByteMask = 0xc0;
- static const int kMultiByteValue = 0x80;
- int multi_byte_bytes_seen = 0;
- while (answer > 0) {
- int c = buffer[answer - 1];
- // Ends in valid single-byte sequence?
- if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) return answer;
- // Ends in one or more subsequent bytes of a multi-byte value?
- if ((c & kMultiByteMask) == kMultiByteValue) {
- multi_byte_bytes_seen++;
- answer--;
- } else {
- if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
- if (multi_byte_bytes_seen >= 1) {
- return answer + 2;
- }
- return answer - 1;
- } else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
- if (multi_byte_bytes_seen >= 2) {
- return answer + 3;
- }
- return answer - 1;
- } else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
- if (multi_byte_bytes_seen >= 3) {
- return answer + 4;
- }
- return answer - 1;
- } else {
- return answer; // Malformed UTF-8.
- }
- }
- }
- return 0;
-}
-
-
-// Suspends the thread until there is data available from the child process.
-// Returns false on timeout, true on data ready.
-static bool WaitOnFD(int fd,
- int read_timeout,
- int total_timeout,
- struct timeval& start_time) {
- fd_set readfds, writefds, exceptfds;
- struct timeval timeout;
- int gone = 0;
- if (total_timeout != -1) {
- struct timeval time_now;
- gettimeofday(&time_now, NULL);
- int seconds = time_now.tv_sec - start_time.tv_sec;
- gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000;
- if (gone >= total_timeout) return false;
- }
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- FD_SET(fd, &readfds);
- FD_SET(fd, &exceptfds);
- if (read_timeout == -1 ||
- (total_timeout != -1 && total_timeout - gone < read_timeout)) {
- read_timeout = total_timeout - gone;
- }
- timeout.tv_usec = (read_timeout % 1000) * 1000;
- timeout.tv_sec = read_timeout / 1000;
- int number_of_fds_ready = select(fd + 1,
- &readfds,
- &writefds,
- &exceptfds,
- read_timeout != -1 ? &timeout : NULL);
- return number_of_fds_ready == 1;
-}
-
-
-// Checks whether we ran out of time on the timeout. Returns true if we ran out
-// of time, false if we still have time.
-static bool TimeIsOut(const struct timeval& start_time, const int& total_time) {
- if (total_time == -1) return false;
- struct timeval time_now;
- gettimeofday(&time_now, NULL);
- // Careful about overflow.
- int seconds = time_now.tv_sec - start_time.tv_sec;
- if (seconds > 100) {
- if (seconds * 1000 > total_time) return true;
- return false;
- }
- int useconds = time_now.tv_usec - start_time.tv_usec;
- if (seconds * 1000000 + useconds > total_time * 1000) {
- return true;
- }
- return false;
-}
-
-
-// A utility class that does a non-hanging waitpid on the child process if we
-// bail out of the System() function early. If you don't ever do a waitpid on
-// a subprocess then it turns into one of those annoying 'zombie processes'.
-class ZombieProtector {
- public:
- explicit ZombieProtector(int pid): pid_(pid) { }
- ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); }
- void ChildIsDeadNow() { pid_ = 0; }
- private:
- int pid_;
-};
-
-
-// A utility class that closes a file descriptor when it goes out of scope.
-class OpenFDCloser {
- public:
- explicit OpenFDCloser(int fd): fd_(fd) { }
- ~OpenFDCloser() { close(fd_); }
- private:
- int fd_;
-};
-
-
-// A utility class that takes the array of command arguments and puts then in an
-// array of new[]ed UTF-8 C strings. Deallocates them again when it goes out of
-// scope.
-class ExecArgs {
- public:
- ExecArgs() {
- exec_args_[0] = NULL;
- }
- bool Init(Handle<Value> arg0, Handle<Array> command_args) {
- String::Utf8Value prog(arg0);
- 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;
- int i = 1;
- 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++) {
- if (exec_args_[i] == NULL) {
- return;
- }
- delete [] exec_args_[i];
- exec_args_[i] = 0;
- }
- }
- static const unsigned kMaxArgs = 1000;
- char** arg_array() { return exec_args_; }
- char* arg0() { return exec_args_[0]; }
- private:
- char* exec_args_[kMaxArgs + 1];
-};
-
-
-// Gets the optional timeouts from the arguments to the system() call.
-static bool GetTimeouts(const Arguments& args,
- int* read_timeout,
- int* total_timeout) {
- if (args.Length() > 3) {
- if (args[3]->IsNumber()) {
- *total_timeout = args[3]->Int32Value();
- } else {
- ThrowException(String::New("system: Argument 4 must be a number"));
- return false;
- }
- }
- if (args.Length() > 2) {
- if (args[2]->IsNumber()) {
- *read_timeout = args[2]->Int32Value();
- } else {
- ThrowException(String::New("system: Argument 3 must be a number"));
- return false;
- }
- }
- return true;
-}
-
-
-static const int kReadFD = 0;
-static const int kWriteFD = 1;
-
-
-// This is run in the child process after fork() but before exec(). It normally
-// ends with the child process being replaced with the desired child program.
-// It only returns if an error occurred.
-static void ExecSubprocess(int* exec_error_fds,
- int* stdout_fds,
- ExecArgs& exec_args) {
- close(exec_error_fds[kReadFD]); // Don't need this in the child.
- close(stdout_fds[kReadFD]); // Don't need this in the child.
- close(1); // Close stdout.
- dup2(stdout_fds[kWriteFD], 1); // Dup pipe fd to stdout.
- close(stdout_fds[kWriteFD]); // Don't need the original fd now.
- fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
- execvp(exec_args.arg0(), exec_args.arg_array());
- // Only get here if the exec failed. Write errno to the parent to tell
- // them it went wrong. If it went well the pipe is closed.
- int err = errno;
- int bytes_written;
- do {
- bytes_written = write(exec_error_fds[kWriteFD], &err, sizeof(err));
- } while (bytes_written == -1 && errno == EINTR);
- // Return (and exit child process).
-}
-
-
-// Runs in the parent process. Checks that the child was able to exec (closing
-// the file desriptor), or reports an error if it failed.
-static bool ChildLaunchedOK(int* exec_error_fds) {
- int bytes_read;
- int err;
- do {
- bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
- } while (bytes_read == -1 && errno == EINTR);
- if (bytes_read != 0) {
- ThrowException(String::New(strerror(err)));
- return false;
- }
- return true;
-}
-
-
-// Accumulates the output from the child in a string handle. Returns true if it
-// succeeded or false if an exception was thrown.
-static Handle<Value> GetStdout(int child_fd,
- struct timeval& start_time,
- int read_timeout,
- int total_timeout) {
- Handle<String> accumulator = String::Empty();
- const char* source = "(function(a, b) { return a + b; })";
- Handle<Value> cons_as_obj(Script::Compile(String::New(source))->Run());
- Handle<Function> cons_function(Function::Cast(*cons_as_obj));
- Handle<Value> cons_args[2];
-
- int fullness = 0;
- static const int kStdoutReadBufferSize = 4096;
- char buffer[kStdoutReadBufferSize];
-
- if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
- return ThrowException(String::New(strerror(errno)));
- }
-
- int bytes_read;
- do {
- bytes_read = read(child_fd,
- buffer + fullness,
- kStdoutReadBufferSize - fullness);
- if (bytes_read == -1) {
- if (errno == EAGAIN) {
- if (!WaitOnFD(child_fd,
- read_timeout,
- total_timeout,
- start_time) ||
- (TimeIsOut(start_time, total_timeout))) {
- return ThrowException(String::New("Timed out waiting for output"));
- }
- continue;
- } else if (errno == EINTR) {
- continue;
- } else {
- break;
- }
- }
- if (bytes_read + fullness > 0) {
- int length = bytes_read == 0 ?
- bytes_read + fullness :
- LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
- Handle<String> addition = String::New(buffer, length);
- cons_args[0] = accumulator;
- cons_args[1] = addition;
- accumulator = Handle<String>::Cast(cons_function->Call(
- Shell::utility_context()->Global(),
- 2,
- cons_args));
- fullness = bytes_read + fullness - length;
- memcpy(buffer, buffer + length, fullness);
- }
- } while (bytes_read != 0);
- return accumulator;
-}
-
-
-// Modern Linux has the waitid call, which is like waitpid, but more useful
-// if you want a timeout. If we don't have waitid we can't limit the time
-// waiting for the process to exit without losing the information about
-// whether it exited normally. In the common case this doesn't matter because
-// we don't get here before the child has closed stdout and most programs don't
-// do that before they exit.
-//
-// We're disabling usage of waitid in Mac OS X because it doens't work for us:
-// a parent process hangs on waiting while a child process is already a zombie.
-// See http://code.google.com/p/v8/issues/detail?id=401.
-#if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__)
-#if !defined(__FreeBSD__)
-#define HAS_WAITID 1
-#endif
-#endif
-
-
-// Get exit status of child.
-static bool WaitForChild(int pid,
- ZombieProtector& child_waiter,
- struct timeval& start_time,
- int read_timeout,
- int total_timeout) {
-#ifdef HAS_WAITID
-
- siginfo_t child_info;
- child_info.si_pid = 0;
- int useconds = 1;
- // Wait for child to exit.
- while (child_info.si_pid == 0) {
- waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
- usleep(useconds);
- if (useconds < 1000000) useconds <<= 1;
- if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
- (TimeIsOut(start_time, total_timeout))) {
- ThrowException(String::New("Timed out waiting for process to terminate"));
- kill(pid, SIGINT);
- return false;
- }
- }
- if (child_info.si_code == CLD_KILLED) {
- char message[999];
- snprintf(message,
- sizeof(message),
- "Child killed by signal %d",
- child_info.si_status);
- ThrowException(String::New(message));
- return false;
- }
- if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
- char message[999];
- snprintf(message,
- sizeof(message),
- "Child exited with status %d",
- child_info.si_status);
- ThrowException(String::New(message));
- return false;
- }
-
-#else // No waitid call.
-
- int child_status;
- waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit.
- child_waiter.ChildIsDeadNow();
- if (WIFSIGNALED(child_status)) {
- char message[999];
- snprintf(message,
- sizeof(message),
- "Child killed by signal %d",
- WTERMSIG(child_status));
- ThrowException(String::New(message));
- return false;
- }
- if (WEXITSTATUS(child_status) != 0) {
- char message[999];
- int exit_status = WEXITSTATUS(child_status);
- snprintf(message,
- sizeof(message),
- "Child exited with status %d",
- exit_status);
- ThrowException(String::New(message));
- return false;
- }
-
-#endif // No waitid call.
-
- return true;
-}
-
-
-// Implementation of the system() function (see d8.h for details).
-Handle<Value> Shell::System(const Arguments& args) {
- HandleScope scope;
- int read_timeout = -1;
- int total_timeout = -1;
- if (!GetTimeouts(args, &read_timeout, &total_timeout)) return v8::Undefined();
- Handle<Array> command_args;
- if (args.Length() > 1) {
- if (!args[1]->IsArray()) {
- return ThrowException(String::New("system: Argument 2 must be an array"));
- }
- command_args = Handle<Array>::Cast(args[1]);
- } else {
- command_args = Array::New(0);
- }
- if (command_args->Length() > ExecArgs::kMaxArgs) {
- return ThrowException(String::New("Too many arguments to system()"));
- }
- if (args.Length() < 1) {
- return ThrowException(String::New("Too few arguments to system()"));
- }
-
- struct timeval start_time;
- gettimeofday(&start_time, NULL);
-
- ExecArgs exec_args;
- if (!exec_args.Init(args[0], command_args)) {
- return v8::Undefined();
- }
- int exec_error_fds[2];
- int stdout_fds[2];
-
- if (pipe(exec_error_fds) != 0) {
- return ThrowException(String::New("pipe syscall failed."));
- }
- if (pipe(stdout_fds) != 0) {
- return ThrowException(String::New("pipe syscall failed."));
- }
-
- pid_t pid = fork();
- if (pid == 0) { // Child process.
- ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
- exit(1);
- }
-
- // Parent process. Ensure that we clean up if we exit this function early.
- ZombieProtector child_waiter(pid);
- close(exec_error_fds[kWriteFD]);
- close(stdout_fds[kWriteFD]);
- OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
- OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
-
- if (!ChildLaunchedOK(exec_error_fds)) return v8::Undefined();
-
- Handle<Value> accumulator = GetStdout(stdout_fds[kReadFD],
- start_time,
- read_timeout,
- total_timeout);
- if (accumulator->IsUndefined()) {
- kill(pid, SIGINT); // On timeout, kill the subprocess.
- return accumulator;
- }
-
- if (!WaitForChild(pid,
- child_waiter,
- start_time,
- read_timeout,
- total_timeout)) {
- return v8::Undefined();
- }
-
- 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();
-}
-
-
-Handle<Value> Shell::SetUMask(const Arguments& args) {
- if (args.Length() != 1) {
- const char* message = "umask() takes one argument";
- return ThrowException(String::New(message));
- }
- if (args[0]->IsNumber()) {
- mode_t mask = args[0]->Int32Value();
- int previous = umask(mask);
- return Number::New(previous);
- } else {
- const char* message = "umask() argument must be numeric";
- return ThrowException(String::New(message));
- }
-}
-
-
-static bool CheckItsADirectory(char* directory) {
- struct stat stat_buf;
- int stat_result = stat(directory, &stat_buf);
- if (stat_result != 0) {
- ThrowException(String::New(strerror(errno)));
- return false;
- }
- if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
- ThrowException(String::New(strerror(EEXIST)));
- return false;
-}
-
-
-// Returns true for success. Creates intermediate directories as needed. No
-// error if the directory exists already.
-static bool mkdirp(char* directory, mode_t mask) {
- int result = mkdir(directory, mask);
- if (result == 0) return true;
- if (errno == EEXIST) {
- return CheckItsADirectory(directory);
- } else if (errno == ENOENT) { // Intermediate path element is missing.
- char* last_slash = strrchr(directory, '/');
- if (last_slash == NULL) {
- ThrowException(String::New(strerror(errno)));
- return false;
- }
- *last_slash = 0;
- if (!mkdirp(directory, mask)) return false;
- *last_slash = '/';
- result = mkdir(directory, mask);
- if (result == 0) return true;
- if (errno == EEXIST) {
- return CheckItsADirectory(directory);
- }
- ThrowException(String::New(strerror(errno)));
- return false;
- } else {
- ThrowException(String::New(strerror(errno)));
- return false;
- }
-}
-
-
-Handle<Value> Shell::MakeDirectory(const Arguments& args) {
- mode_t mask = 0777;
- if (args.Length() == 2) {
- if (args[1]->IsNumber()) {
- mask = args[1]->Int32Value();
- } else {
- const char* message = "mkdirp() second argument must be numeric";
- return ThrowException(String::New(message));
- }
- } else if (args.Length() != 1) {
- const char* message = "mkdirp() takes one or two arguments";
- return ThrowException(String::New(message));
- }
- String::Utf8Value directory(args[0]);
- if (*directory == NULL) {
- const char* message = "os.mkdirp(): String conversion of argument failed.";
- return ThrowException(String::New(message));
- }
- mkdirp(*directory, mask);
- return v8::Undefined();
-}
-
-
-Handle<Value> Shell::RemoveDirectory(const Arguments& args) {
- if (args.Length() != 1) {
- const char* message = "rmdir() takes one or two arguments";
- return ThrowException(String::New(message));
- }
- String::Utf8Value directory(args[0]);
- if (*directory == NULL) {
- const char* message = "os.rmdir(): String conversion of argument failed.";
- return ThrowException(String::New(message));
- }
- rmdir(*directory);
- return v8::Undefined();
-}
-
-
-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::UnsetEnvironment(const Arguments& args) {
- if (args.Length() != 1) {
- const char* message = "unsetenv() takes one argument";
- return ThrowException(String::New(message));
- }
- String::Utf8Value var(args[0]);
- if (*var == NULL) {
- const char* message =
- "os.setenv(): String conversion of variable name failed.";
- return ThrowException(String::New(message));
- }
- unsetenv(*var);
- return v8::Undefined();
-}
-
-
-void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
- 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));
- os_templ->Set(String::New("unsetenv"),
- FunctionTemplate::New(UnsetEnvironment));
- os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask));
- os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory));
- os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory));
-}
-
-} // namespace v8
128 v8/src/d8-readline.cc
View
@@ -1,128 +0,0 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include <cstdio> // NOLINT
-#include <readline/readline.h> // NOLINT
-#include <readline/history.h> // NOLINT
-
-
-#include "d8.h"
-
-
-// There are incompatibilities between different versions and different
-// implementations of readline. This smooths out one known incompatibility.
-#if RL_READLINE_VERSION >= 0x0500
-#define completion_matches rl_completion_matches
-#endif
-
-
-namespace v8 {
-
-
-class ReadLineEditor: public LineEditor {
- public:
- ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
- virtual i::SmartPointer<char> Prompt(const char* prompt);
- virtual bool Open();
- virtual bool Close();
- virtual void AddHistory(const char* str);
- private:
- static char** AttemptedCompletion(const char* text, int start, int end);
- static char* CompletionGenerator(const char* text, int state);
- static char kWordBreakCharacters[];
-};
-
-
-static ReadLineEditor read_line_editor;
-char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
- '\\', '\'', '`', '@', '.', '>', '<', '=', ';', '|', '&', '{', '(',
- '\0'};
-
-
-bool ReadLineEditor::Open() {
- rl_initialize();
- rl_attempted_completion_function = AttemptedCompletion;
- rl_completer_word_break_characters = kWordBreakCharacters;
- rl_bind_key('\t', rl_complete);
- using_history();
- return read_history(Shell::kHistoryFileName) == 0;
-}
-
-
-bool ReadLineEditor::Close() {
- return write_history(Shell::kHistoryFileName) == 0;
-}
-
-
-i::SmartPointer<char> ReadLineEditor::Prompt(const char* prompt) {
- char* result = readline(prompt);
- return i::SmartPointer<char>(result);
-}
-
-
-void ReadLineEditor::AddHistory(const char* str) {
- add_history(str);
-}
-
-
-char** ReadLineEditor::AttemptedCompletion(const char* text,
- int start,
- int end) {
- char** result = completion_matches(text, CompletionGenerator);
- rl_attempted_completion_over = true;
- return result;
-}
-
-
-char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
- static unsigned current_index;
- static Persistent<Array> current_completions;
- if (state == 0) {
- i::SmartPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
- HandleScope scope;
- Handle<Array> completions =
- Shell::GetCompletions(String::New(text), String::New(*full_text));
- current_completions = Persistent<Array>::New(completions);
- current_index = 0;
- }
- if (current_index < current_completions->Length()) {
- HandleScope scope;
- Handle<Integer> index = Integer::New(current_index);
- Handle<Value> str_obj = current_completions->Get(index);
- current_index++;
- String::Utf8Value str(str_obj);
- return strdup(*str);
- } else {
- current_completions.Dispose();
- current_completions.Clear();
- return NULL;
- }
-}
-
-
-} // namespace v8
42 v8/src/d8-windows.cc
View
@@ -1,42 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "d8.h"
-#include "d8-debug.h"
-#include "debug.h"
-#include "api.h"
-
-
-namespace v8 {
-
-
-void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
-}
-
-
-} // namespace v8
796 v8/src/d8.cc
View
@@ -1,796 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include "v8.h"
-
-#include "d8.h"
-#include "d8-debug.h"
-#include "debug.h"
-#include "api.h"
-#include "natives.h"
-#include "platform.h"
-
-
-namespace v8 {
-
-
-const char* Shell::kHistoryFileName = ".d8_history";
-const char* Shell::kPrompt = "d8> ";
-
-
-LineEditor *LineEditor::first_ = NULL;
-
-
-LineEditor::LineEditor(Type type, const char* name)
- : type_(type),
- name_(name),
- next_(first_) {
- first_ = this;
-}
-
-
-LineEditor* LineEditor::Get() {
- LineEditor* current = first_;
- LineEditor* best = current;
- while (current != NULL) {
- if (current->type_ > best->type_)
- best = current;
- current = current->next_;
- }
- return best;
-}
-
-
-class DumbLineEditor: public LineEditor {
- public:
- DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
- virtual i::SmartPointer<char> Prompt(const char* prompt);
-};
-
-
-static DumbLineEditor dumb_line_editor;
-
-
-i::SmartPointer<char> DumbLineEditor::Prompt(const char* prompt) {
- static const int kBufferSize = 256;
- char buffer[kBufferSize];
- printf("%s", prompt);
- char* str = fgets(buffer, kBufferSize, stdin);
- return i::SmartPointer<char>(str ? i::StrDup(str) : str);
-}
-
-
-CounterMap* Shell::counter_map_;
-i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
-CounterCollection Shell::local_counters_;
-CounterCollection* Shell::counters_ = &local_counters_;
-Persistent<Context> Shell::utility_context_;
-Persistent<Context> Shell::evaluation_context_;
-
-
-bool CounterMap::Match(void* key1, void* key2) {
- const char* name1 = reinterpret_cast<const char*>(key1);
- const char* name2 = reinterpret_cast<const char*>(key2);
- return strcmp(name1, name2) == 0;
-}
-
-
-// Converts a V8 value to a C string.
-const char* Shell::ToCString(const v8::String::Utf8Value& value) {
- return *value ? *value : "<string conversion failed>";
-}
-
-
-// Executes a string within the current v8 context.
-bool Shell::ExecuteString(Handle<String> source,
- Handle<Value> name,
- bool print_result,
- bool report_exceptions) {
- HandleScope handle_scope;
- TryCatch try_catch;
- if (i::FLAG_debugger) {
- // When debugging make exceptions appear to be uncaught.
- try_catch.SetVerbose(true);
- }
- Handle<Script> script = Script::Compile(source, name);
- if (script.IsEmpty()) {
- // Print errors that happened during compilation.
- if (report_exceptions && !i::FLAG_debugger)
- ReportException(&try_catch);
- return false;
- } else {
- Handle<Value> result = script->Run();
- if (result.IsEmpty()) {
- ASSERT(try_catch.HasCaught());
- // Print errors that happened during execution.
- if (report_exceptions && !i::FLAG_debugger)
- ReportException(&try_catch);
- return false;
- } else {
- ASSERT(!try_catch.HasCaught());
- if (print_result && !result->IsUndefined()) {
- // If all went well and the result wasn't undefined then print
- // the returned value.
- v8::String::Utf8Value str(result);
- const char* cstr = ToCString(str);
- printf("%s\n", cstr);
- }
- return true;
- }
- }
-}
-
-
-Handle<Value> Shell::Print(const Arguments& args) {
- Handle<Value> val = Write(args);
- printf("\n");
- return val;
-}
-
-
-Handle<Value> Shell::Write(const Arguments& args) {
- for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
- if (i != 0) {
- printf(" ");
- }
- v8::String::Utf8Value str(args[i]);
- int n = fwrite(*str, sizeof(**str), str.length(), stdout);
- if (n != str.length()) {
- printf("Error in fwrite\n");
- exit(1);
- }
- }
- return Undefined();
-}
-
-
-Handle<Value> Shell::Read(const Arguments& args) {
- String::Utf8Value file(args[0]);
- if (*file == NULL) {
- return ThrowException(String::New("Error loading file"));
- }
- Handle<String> source = ReadFile(*file);
- if (source.IsEmpty()) {
- return ThrowException(String::New("Error loading file"));
- }
- return source;
-}
-
-
-Handle<Value> Shell::ReadLine(const Arguments& args) {
- i::SmartPointer<char> line(i::ReadLine(""));
- if (*line == NULL) {
- return Null();
- }
- size_t len = strlen(*line);
- if (len > 0 && line[len - 1] == '\n') {
- --len;
- }
- return String::New(*line, len);
-}
-
-
-Handle<Value> Shell::Load(const Arguments& args) {
- for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
- String::Utf8Value file(args[i]);
- if (*file == NULL) {
- return ThrowException(String::New("Error loading file"));
- }
- Handle<String> source = ReadFile(*file);
- if (source.IsEmpty()) {
- return ThrowException(String::New("Error loading file"));
- }
- if (!ExecuteString(source, String::New(*file), false, false)) {
- return ThrowException(String::New("Error executing file"));
- }
- }
- return Undefined();
-}
-
-
-Handle<Value> Shell::Yield(const Arguments& args) {
- v8::Unlocker unlocker;
- return Undefined();
-}
-
-
-Handle<Value> Shell::Quit(const Arguments& args) {
- int exit_code = args[0]->Int32Value();
- OnExit();
- exit(exit_code);
- return Undefined();
-}
-
-
-Handle<Value> Shell::Version(const Arguments& args) {
- return String::New(V8::GetVersion());
-}
-
-
-void Shell::ReportException(v8::TryCatch* try_catch) {
- HandleScope handle_scope;
- v8::String::Utf8Value exception(try_catch->Exception());
- const char* exception_string = ToCString(exception);
- Handle<Message> message = try_catch->Message();
- if (message.IsEmpty()) {
- // V8 didn't provide any extra information about this error; just
- // print the exception.
- printf("%s\n", exception_string);
- } else {
- // Print (filename):(line number): (message).
- v8::String::Utf8Value filename(message->GetScriptResourceName());
- const char* filename_string = ToCString(filename);
- int linenum = message->GetLineNumber();
- printf("%s:%i: %s\n", filename_string, linenum, exception_string);
- // Print line of source code.
- v8::String::Utf8Value sourceline(message->GetSourceLine());
- const char* sourceline_string = ToCString(sourceline);
- printf("%s\n", sourceline_string);
- // Print wavy underline (GetUnderline is deprecated).
- int start = message->GetStartColumn();
- for (int i = 0; i < start; i++) {
- printf(" ");
- }
- int end = message->GetEndColumn();
- for (int i = start; i < end; i++) {
- printf("^");
- }
- printf("\n");
- }
-}
-
-
-Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
- HandleScope handle_scope;
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("GetCompletions"));
- static const int kArgc = 3;
- Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
- Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return handle_scope.Close(Handle<Array>::Cast(val));
-}
-
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
-Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
- static const int kArgc = 1;
- Handle<Value> argv[kArgc] = { message };
- Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return Handle<Object>::Cast(val);
-}
-
-
-Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
- Context::Scope context_scope(utility_context_);
- Handle<Object> global = utility_context_->Global();
- Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
- static const int kArgc = 1;
- Handle<Value> argv[kArgc] = { command };
- Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
- return val;
-}
-#endif
-
-
-int32_t* Counter::Bind(const char* name, bool is_histogram) {
- int i;
- for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
- name_[i] = static_cast<char>(name[i]);
- name_[i] = '\0';
- is_histogram_ = is_histogram;
- return ptr();
-}
-
-
-void Counter::AddSample(int32_t sample) {
- count_++;
- sample_total_ += sample;
-}
-
-
-CounterCollection::CounterCollection() {
- magic_number_ = 0xDEADFACE;
- max_counters_ = kMaxCounters;
- max_name_size_ = Counter::kMaxNameSize;
- counters_in_use_ = 0;
-}
-
-
-Counter* CounterCollection::GetNextCounter() {
- if (counters_in_use_ == kMaxCounters) return NULL;
- return &counters_[counters_in_use_++];
-}
-
-
-void Shell::MapCounters(const char* name) {
- counters_file_ = i::OS::MemoryMappedFile::create(name,
- sizeof(CounterCollection), &local_counters_);
- void* memory = (counters_file_ == NULL) ?
- NULL : counters_file_->memory();
- if (memory == NULL) {
- printf("Could not map counters file %s\n", name);
- exit(1);
- }
- counters_ = static_cast<CounterCollection*>(memory);
- V8::SetCounterFunction(LookupCounter);
- V8::SetCreateHistogramFunction(CreateHistogram);
- V8::SetAddHistogramSampleFunction(AddHistogramSample);
-}
-
-
-int CounterMap::Hash(const char* name) {
- int h = 0;
- int c;
- while ((c = *name++) != 0) {
- h += h << 5;
- h += c;
- }
- return h;
-}
-
-
-Counter* Shell::GetCounter(const char* name, bool is_histogram) {
- Counter* counter = counter_map_->Lookup(name);
-
- if (counter == NULL) {
- counter = counters_->GetNextCounter();
- if (counter != NULL) {
- counter_map_->Set(name, counter);
- counter->Bind(name, is_histogram);
- }
- } else {
- ASSERT(counter->is_histogram() == is_histogram);
- }
- return counter;
-}
-
-
-int* Shell::LookupCounter(const char* name) {
- Counter* counter = GetCounter(name, false);
-
- if (counter != NULL) {
- return counter->ptr();
- } else {
- return NULL;
- }
-}
-
-
-void* Shell::CreateHistogram(const char* name,
- int min,
- int max,
- size_t buckets) {
- return GetCounter(name, true);
-}
-
-
-void Shell::AddHistogramSample(void* histogram, int sample) {
- Counter* counter = reinterpret_cast<Counter*>(histogram);
- counter->AddSample(sample);
-}
-
-
-void Shell::Initialize() {
- Shell::counter_map_ = new CounterMap();
- // Set up counters
- if (i::StrLength(i::FLAG_map_counters) != 0)
- MapCounters(i::FLAG_map_counters);
- if (i::FLAG_dump_counters) {
- V8::SetCounterFunction(LookupCounter);
- V8::SetCreateHistogramFunction(CreateHistogram);
- V8::SetAddHistogramSampleFunction(AddHistogramSample);
- }
-
- // Initialize the global objects
- HandleScope scope;
- Handle<ObjectTemplate> global_template = ObjectTemplate::New();
- global_template->Set(String::New("print"), FunctionTemplate::New(Print));
- global_template->Set(String::New("write"), FunctionTemplate::New(Write));
- global_template->Set(String::New("read"), FunctionTemplate::New(Read));
- global_template->Set(String::New("readline"),
- FunctionTemplate::New(ReadLine));
- 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));
-
-#ifdef LIVE_OBJECT_LIST
- global_template->Set(String::New("lol_is_enabled"), Boolean::New(true));
-#else
- global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
-#endif
-
- Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
- AddOSMethods(os_templ);
- global_template->Set(String::New("os"), os_templ);
-
- utility_context_ = Context::New(NULL, global_template);
- utility_context_->SetSecurityToken(Undefined());
- Context::Scope utility_scope(utility_context_);
-
- i::JSArguments js_args = i::FLAG_js_arguments;
- i::Handle<i::FixedArray> arguments_array =
- FACTORY->NewFixedArray(js_args.argc());
- for (int j = 0; j < js_args.argc(); j++) {
- i::Handle<i::String> arg =
- FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
- arguments_array->set(j, *arg);
- }
- i::Handle<i::JSArray> arguments_jsarray =
- FACTORY->NewJSArrayWithElements(arguments_array);
- global_template->Set(String::New("arguments"),
- Utils::ToLocal(arguments_jsarray));
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Install the debugger object in the utility scope
- i::Debug* debug = i::Isolate::Current()->debug();
- debug->Load();
- i::Handle<i::JSObject> js_debug
- = i::Handle<i::JSObject>(debug->debug_context()->global());
- utility_context_->Global()->Set(String::New("$debug"),
- Utils::ToLocal(js_debug));
-#endif
-
- // Run the d8 shell utility script in the utility context
- int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
- i::Vector<const char> shell_source
- = i::NativesCollection<i::D8>::GetScriptSource(source_index);
- i::Vector<const char> shell_source_name
- = i::NativesCollection<i::D8>::GetScriptName(source_index);
- Handle<String> source = String::New(shell_source.start(),
- shell_source.length());
- Handle<String> name = String::New(shell_source_name.start(),
- shell_source_name.length());
- Handle<Script> script = Script::Compile(source, name);
- script->Run();
-
- // Mark the d8 shell script as native to avoid it showing up as normal source
- // in the debugger.
- i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
- i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
- ? i::Handle<i::Script>(i::Script::cast(
- i::JSFunction::cast(*compiled_script)->shared()->script()))
- : i::Handle<i::Script>(i::Script::cast(
- i::SharedFunctionInfo::cast(*compiled_script)->script()));
- script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
-
- // Create the evaluation context
- evaluation_context_ = Context::New(NULL, global_template);
- evaluation_context_->SetSecurityToken(Undefined());
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Set the security token of the debug context to allow access.
- debug->debug_context()->set_security_token(HEAP->undefined_value());
-
- // Start the debugger agent if requested.
- if (i::FLAG_debugger_agent) {
- v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
- }
-
- // Start the in-process debugger if requested.
- if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
- v8::Debug::SetDebugEventListener(HandleDebugEvent);
- }
-#endif
-}
-
-
-void Shell::OnExit() {
- if (i::FLAG_dump_counters) {
- ::printf("+----------------------------------------+-------------+\n");
- ::printf("| Name | Value |\n");
- ::printf("+----------------------------------------+-------------+\n");
- for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
- Counter* counter = i.CurrentValue();
- if (counter->is_histogram()) {
- ::printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
- ::printf("| t:%-36s | %11i |\n",
- i.CurrentKey(),
- counter->sample_total());
- } else {
- ::printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
- }
- }
- ::printf("+----------------------------------------+-------------+\n");
- }
- if (counters_file_ != NULL)
- delete counters_file_;
-}
-
-
-static char* ReadChars(const char* name, int* size_out) {
- v8::Unlocker unlocker; // Release the V8 lock while reading files.
- FILE* file = i::OS::FOpen(name, "rb");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
- rewind(file);
-
- char* chars = new char[size + 1];
- chars[size] = '\0';
- for (int i = 0; i < size;) {
- int read = fread(&chars[i], 1, size - i, file);
- i += read;
- }
- fclose(file);
- *size_out = size;
- return chars;
-}
-
-
-static char* ReadToken(char* data, char token) {
- char* next = i::OS::StrChr(data, token);
- if (next != NULL) {
- *next = '\0';
- return (next + 1);
- }
-
- return NULL;
-}
-
-
-static char* ReadLine(char* data) {
- return ReadToken(data, '\n');
-}
-
-
-static char* ReadWord(char* data) {
- return ReadToken(data, ' ');
-}
-
-
-// Reads a file into a v8 string.
-Handle<String> Shell::ReadFile(const char* name) {
- int size = 0;
- char* chars = ReadChars(name, &size);
- if (chars == NULL) return Handle<String>();
- Handle<String> result = String::New(chars);
- delete[] chars;
- return result;
-}
-
-
-void Shell::RunShell() {
- LineEditor* editor = LineEditor::Get();
- printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
- if (i::FLAG_debugger) {
- printf("JavaScript debugger enabled\n");
- }
- editor->Open();
- while (true) {
- Locker locker;
- HandleScope handle_scope;
- Context::Scope context_scope(evaluation_context_);
- i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
- if (input.is_empty())
- break;
- editor->AddHistory(*input);
- Handle<String> name = String::New("(d8)");
- ExecuteString(String::New(*input), name, true, true);
- }
- editor->Close();
- printf("\n");
-}
-
-
-class ShellThread : public i::Thread {
- public:
- ShellThread(i::Isolate* isolate, int no, i::Vector<const char> files)
- : Thread(isolate, "d8:ShellThread"),
- no_(no), files_(files) { }
- virtual void Run();
- private:
- int no_;
- i::Vector<const char> files_;
-};
-
-
-void ShellThread::Run() {
- // Prepare the context for this thread.
- Locker locker;
- HandleScope scope;
- Handle<ObjectTemplate> global_template = ObjectTemplate::New();
- global_template->Set(String::New("print"),
- FunctionTemplate::New(Shell::Print));
- global_template->Set(String::New("write"),
- FunctionTemplate::New(Shell::Write));
- global_template->Set(String::New("read"),
- FunctionTemplate::New(Shell::Read));
- global_template->Set(String::New("readline"),
- FunctionTemplate::New(Shell::ReadLine));
- global_template->Set(String::New("load"),
- FunctionTemplate::New(Shell::Load));
- global_template->Set(String::New("yield"),
- FunctionTemplate::New(Shell::Yield));
- global_template->Set(String::New("version"),
- FunctionTemplate::New(Shell::Version));
-
- char* ptr = const_cast<char*>(files_.start());
- while ((ptr != NULL) && (*ptr != '\0')) {
- // For each newline-separated line.
- char* next_line = ReadLine(ptr);
-
- if (*ptr == '#') {
- // Skip comment lines.
- ptr = next_line;
- continue;
- }
-
- Persistent<Context> thread_context = Context::New(NULL, global_template);
- thread_context->SetSecurityToken(Undefined());
- Context::Scope context_scope(thread_context);
-
- while ((ptr != NULL) && (*ptr != '\0')) {
- char* filename = ptr;
- ptr = ReadWord(ptr);
-
- // Skip empty strings.
- if (strlen(filename) == 0) {
- break;
- }
-
- Handle<String> str = Shell::ReadFile(filename);
- if (str.IsEmpty()) {
- printf("WARNING: %s not found\n", filename);
- break;
- }
-
- Shell::ExecuteString(str, String::New(filename), false, false);
- }
-
- thread_context.Dispose();
- ptr = next_line;
- }
-}
-
-
-int Shell::Main(int argc, char* argv[]) {
- i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
- if (i::FLAG_help) {
- return 1;
- }
- Initialize();
- bool run_shell = (argc == 1);
-
- // Default use preemption if threads are created.
- bool use_preemption = true;
-
- // Default to use lowest possible thread preemption interval to test as many
- // edgecases as possible.
- int preemption_interval = 1;
-
- i::List<i::Thread*> threads(1);
-
- {
- // Acquire the V8 lock once initialization has finished. Since the thread
- // below may spawn new threads accessing V8 holding the V8 lock here is
- // mandatory.
- Locker locker;
- Context::Scope context_scope(evaluation_context_);
- for (int i = 1; i < argc; i++) {
- char* str = argv[i];
- if (strcmp(str, "--shell") == 0) {
- run_shell = true;
- } else if (strcmp(str, "--preemption") == 0) {
- use_preemption = true;
- } else if (strcmp(str, "--no-preemption") == 0) {
- use_preemption = false;
- } else if (strcmp(str, "--preemption-interval") == 0) {
- if (i + 1 < argc) {
- char* end = NULL;
- preemption_interval = strtol(argv[++i], &end, 10); // NOLINT
- if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
- printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
- return 1;
- }
- } else {
- printf("Missing value for --preemption-interval\n");
- return 1;
- }
- } else if (strcmp(str, "-f") == 0) {
- // Ignore any -f flags for compatibility with other stand-alone
- // JavaScript engines.
- continue;
- } else if (strncmp(str, "--", 2) == 0) {
- printf("Warning: unknown flag %s.\nTry --help for options\n", str);
- } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
- // Execute argument given to -e option directly.
- v8::HandleScope handle_scope;
- v8::Handle<v8::String> file_name = v8::String::New("unnamed");
- v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
- if (!ExecuteString(source, file_name, false, true)) {
- OnExit();
- return 1;
- }
- i++;
- } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
- int size = 0;
- const char* files = ReadChars(argv[++i], &size);
- if (files == NULL) return 1;
- ShellThread* thread =
- new ShellThread(i::Isolate::Current(),
- threads.length(),
- i::Vector<const char>(files, size));
- thread->Start();
- threads.Add(thread);
- } else {
- // Use all other arguments as names of files to load and run.
- HandleScope handle_scope;
- Handle<String> file_name = v8::String::New(str);
- Handle<String> source = ReadFile(str);
- if (source.IsEmpty()) {
- printf("Error reading '%s'\n", str);
- return 1;
- }
- if (!ExecuteString(source, file_name, false, true)) {
- OnExit();
- return 1;
- }
- }
- }
-
- // Start preemption if threads have been created and preemption is enabled.
- if (threads.length() > 0 && use_preemption) {
- Locker::StartPreemption(preemption_interval);
- }
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Run the remote debugger if requested.
- if (i::FLAG_remote_debugger) {
- RunRemoteDebugger(i::FLAG_debugger_port);
- return 0;
- }
-#endif
- }
- if (run_shell)
- RunShell();
- for (int i = 0; i < threads.length(); i++) {
- i::Thread* thread = threads[i];
- thread->Join();
- delete thread;
- }
- OnExit();
- return 0;
-}
-
-
-} // namespace v8
-
-
-int main(int argc, char* argv[]) {
- return v8::Shell::Main(argc, argv);
-}
231 v8/src/d8.h
View
@@ -1,231 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_D8_H_
-#define V8_D8_H_
-
-#include "v8.h"
-#include "hashmap.h"
-
-
-namespace v8 {
-
-
-namespace i = v8::internal;
-
-
-// A single counter in a counter collection.
-class Counter {
- public:
- static const int kMaxNameSize = 64;
- int32_t* Bind(const char* name, bool histogram);
- int32_t* ptr() { return &count_; }
- int32_t count() { return count_; }
- int32_t sample_total() { return sample_total_; }
- bool is_histogram() { return is_histogram_; }
- void AddSample(int32_t sample);
- private:
- int32_t count_;
- int32_t sample_total_;
- bool is_histogram_;
- uint8_t name_[kMaxNameSize];
-};
-
-
-// A set of counters and associated information. An instance of this
-// class is stored directly in the memory-mapped counters file if
-// the --map-counters options is used
-class CounterCollection {
- public:
- CounterCollection();
- Counter* GetNextCounter();
- private:
- static const unsigned kMaxCounters = 256;
- uint32_t magic_number_;
- uint32_t max_counters_;
- uint32_t max_name_size_;
- uint32_t counters_in_use_;
- Counter counters_[kMaxCounters];
-};
-
-
-class CounterMap {
- public:
- CounterMap(): hash_map_(Match) { }
- Counter* Lookup(const char* name) {
- i::HashMap::Entry* answer = hash_map_.Lookup(
- const_cast<char*>(name),
- Hash(name),
- false);
- if (!answer) return NULL;
- return reinterpret_cast<Counter*>(answer->value);
- }
- void Set(const char* name, Counter* value) {
- i::HashMap::Entry* answer = hash_map_.Lookup(
- const_cast<char*>(name),
- Hash(name),
- true);
- ASSERT(answer != NULL);
- answer->value = value;
- }
- class Iterator {
- public:
- explicit Iterator(CounterMap* map)
- : map_(&map->hash_map_), entry_(map_->Start()) { }
- void Next() { entry_ = map_->Next(entry_); }
- bool More() { return entry_ != NULL; }
- const char* CurrentKey() { return static_cast<const char*>(entry_->key); }
- Counter* CurrentValue() { return static_cast<Counter*>(entry_->value); }
- private:
- i::HashMap* map_;
- i::HashMap::Entry* entry_;
- };
- private:
- static int Hash(const char* name);
- static bool Match(void* key1, void* key2);
- i::HashMap hash_map_;
-};
-
-
-class Shell: public i::AllStatic {
- public:
- static bool ExecuteString(Handle<String> source,
- Handle<Value> name,
- bool print_result,
- bool report_exceptions);
- static const char* ToCString(const v8::String::Utf8Value& value);
- static void ReportException(TryCatch* try_catch);
- static void Initialize();
- static void OnExit();
- static int* LookupCounter(const char* name);
- static void* CreateHistogram(const char* name,
- int min,
- int max,
- size_t buckets);
- static void AddHistogramSample(void* histogram, int sample);
- static void MapCounters(const char* name);
- static Handle<String> ReadFile(const char* name);
- static void RunShell();
- static int Main(int argc, char* argv[]);
- static Handle<Array> GetCompletions(Handle<String> text,
- Handle<String> full);
-#ifdef ENABLE_DEBUGGER_SUPPORT
- static Handle<Object> DebugMessageDetails(Handle<String> message);
- static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
-#endif
-
-#ifdef WIN32
-#undef Yield
-#endif
-
- static Handle<Value> Print(const Arguments& args);
- static Handle<Value> Write(const Arguments& args);
- static Handle<Value> Yield(const Arguments& args);
- static Handle<Value> Quit(const Arguments& args);
- static Handle<Value> Version(const Arguments& args);
- static Handle<Value> Read(const Arguments& args);
- static Handle<Value> ReadLine(const Arguments& args);
- static Handle<Value> Load(const Arguments& args);
- // 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.
- // timeout2, if present, should be a number indicating the limit in
- // 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.
- //
- // os.umask(alue) calls the umask system call and returns the old umask.
- //
- // os.mkdirp(name, mask) creates a directory. The mask (if present) is anded
- // with the current umask. Intermediate directories are created if necessary.
- // An exception is not thrown if the directory already exists. Analogous to
- // the "mkdir -p" command.
- 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<Value> UnsetEnvironment(const Arguments& args);
- static Handle<Value> SetUMask(const Arguments& args);
- static Handle<Value> MakeDirectory(const Arguments& args);
- static Handle<Value> RemoveDirectory(const Arguments& args);
-
- static void AddOSMethods(Handle<ObjectTemplate> os_template);
-
- static Handle<Context> utility_context() { return utility_context_; }
-
- static const char* kHistoryFileName;
- static const char* kPrompt;
- private:
- static Persistent<Context> utility_context_;
- static Persistent<Context> evaluation_context_;
- static CounterMap* counter_map_;
- // We statically allocate a set of local counters to be used if we
- // don't want to store the stats in a memory-mapped file
- static CounterCollection local_counters_;
- static CounterCollection* counters_;
- static i::OS::MemoryMappedFile* counters_file_;
- static Counter* GetCounter(const char* name, bool is_histogram);
-};
-
-
-class LineEditor {
- public:
- enum Type { DUMB = 0, READLINE = 1 };
- LineEditor(Type type, const char* name);
- virtual ~LineEditor() { }
-
- virtual i::SmartPointer<char> Prompt(const char* prompt) = 0;
- virtual bool Open() { return true; }
- virtual bool Close() { return true; }
- virtual void AddHistory(const char* str) { }
-
- const char* name() { return name_; }
- static LineEditor* Get();
- private:
- Type type_;
- const char* name_;
- LineEditor* next_;
- static LineEditor* first_;
-};
-
-
-} // namespace v8
-
-
-#endif // V8_D8_H_
Please sign in to comment.
Something went wrong with that request. Please try again.