Index: samples/shell.cc |
diff --git a/samples/shell.cc b/samples/shell.cc |
index 7c30beccd5f3b52a75f286ce7800e49632039e5d..8ed9d032aaf3ab4919e921f96c5185ad61dd7fba 100644 |
--- a/samples/shell.cc |
+++ b/samples/shell.cc |
@@ -26,39 +26,28 @@ |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
#include <v8.h> |
-#include <v8-testing.h> |
#include <assert.h> |
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
-#include <bzlib.h> |
-#endif |
#include <fcntl.h> |
#include <string.h> |
#include <stdio.h> |
#include <stdlib.h> |
-// When building with V8 in a shared library we cannot use functions which |
-// is not explicitly a part of the public V8 API. This extensive use of |
-// #ifndef USING_V8_SHARED/#endif is a hack until we can resolve whether to |
-// still use the shell sample for testing or change to use the developer |
-// shell d8 TODO(1272). |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
-#include "../src/v8.h" |
-#endif // USING_V8_SHARED |
- |
-#if !defined(_WIN32) && !defined(_WIN64) |
-#include <unistd.h> // NOLINT |
+#ifdef COMPRESS_STARTUP_DATA_BZ2 |
+#error Using compressed startup data is not supported for this sample |
#endif |
-static void ExitShell(int exit_code) { |
Yang
2011/07/13 16:08:46
Removed since there is no longer multi-threading.
|
- // Use _exit instead of exit to avoid races between isolate |
- // threads and static destructors. |
- fflush(stdout); |
- fflush(stderr); |
- _exit(exit_code); |
-} |
+/** |
+ * This sample program shows how to implement a simple javascript shell |
+ * based on V8. This includes initializing V8 with command line options, |
+ * creating global functions, compiling and executing strings. |
+ * |
+ * For a more sophisticated shell, consider using the debug shell D8. |
+ */ |
+ |
v8::Persistent<v8::Context> CreateShellContext(); |
void RunShell(v8::Handle<v8::Context> context); |
+int RunMain(int argc, char* argv[]); |
bool ExecuteString(v8::Handle<v8::String> source, |
v8::Handle<v8::Value> name, |
bool print_result, |
@@ -68,298 +57,28 @@ v8::Handle<v8::Value> Read(const v8::Arguments& args); |
v8::Handle<v8::Value> Load(const v8::Arguments& args); |
v8::Handle<v8::Value> Quit(const v8::Arguments& args); |
v8::Handle<v8::Value> Version(const v8::Arguments& args); |
-v8::Handle<v8::Value> Int8Array(const v8::Arguments& args); |
Yang
2011/07/13 16:08:46
Removed external arrays completely.
|
-v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Int16Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Int32Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Float32Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> Float64Array(const v8::Arguments& args); |
-v8::Handle<v8::Value> PixelArray(const v8::Arguments& args); |
v8::Handle<v8::String> ReadFile(const char* name); |
void ReportException(v8::TryCatch* handler); |
-static bool last_run = true; |
- |
Yang
2011/07/13 16:08:46
Removed support for --isolate.
|
-class SourceGroup { |
- public: |
- SourceGroup() : |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- next_semaphore_(v8::internal::OS::CreateSemaphore(0)), |
- done_semaphore_(v8::internal::OS::CreateSemaphore(0)), |
- thread_(NULL), |
-#endif // USING_V8_SHARED |
- argv_(NULL), |
- begin_offset_(0), |
- end_offset_(0) { } |
- |
- void Begin(char** argv, int offset) { |
- argv_ = const_cast<const char**>(argv); |
- begin_offset_ = offset; |
- } |
- |
- void End(int offset) { end_offset_ = offset; } |
- |
- void Execute() { |
- for (int i = begin_offset_; i < end_offset_; ++i) { |
- const char* arg = argv_[i]; |
- if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { |
- // 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)) { |
- ExitShell(1); |
- return; |
- } |
- ++i; |
- } else if (arg[0] == '-') { |
- // Ignore other options. They have been parsed already. |
- } else { |
- // Use all other arguments as names of files to load and run. |
- v8::HandleScope handle_scope; |
- v8::Handle<v8::String> file_name = v8::String::New(arg); |
- v8::Handle<v8::String> source = ReadFile(arg); |
- if (source.IsEmpty()) { |
- printf("Error reading '%s'\n", arg); |
- continue; |
- } |
- if (!ExecuteString(source, file_name, false, true)) { |
- ExitShell(1); |
- return; |
- } |
- } |
- } |
- } |
- |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- void StartExecuteInThread() { |
- if (thread_ == NULL) { |
- thread_ = new IsolateThread(this); |
- thread_->Start(); |
- } |
- next_semaphore_->Signal(); |
- } |
- |
- void WaitForThread() { |
- if (thread_ == NULL) return; |
- if (last_run) { |
- thread_->Join(); |
- thread_ = NULL; |
- } else { |
- done_semaphore_->Wait(); |
- } |
- } |
-#endif // USING_V8_SHARED |
- |
- private: |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- static v8::internal::Thread::Options GetThreadOptions() { |
- v8::internal::Thread::Options options; |
- options.name = "IsolateThread"; |
- // On some systems (OSX 10.6) the stack size default is 0.5Mb or less |
- // which is not enough to parse the big literal expressions used in tests. |
- // The stack size should be at least StackGuard::kLimitSize + some |
- // OS-specific padding for thread startup code. |
- options.stack_size = 2 << 20; // 2 Mb seems to be enough |
- return options; |
- } |
- |
- class IsolateThread : public v8::internal::Thread { |
- public: |
- explicit IsolateThread(SourceGroup* group) |
- : v8::internal::Thread(GetThreadOptions()), group_(group) {} |
- |
- virtual void Run() { |
- group_->ExecuteInThread(); |
- } |
- |
- private: |
- SourceGroup* group_; |
- }; |
- |
- void ExecuteInThread() { |
- v8::Isolate* isolate = v8::Isolate::New(); |
- do { |
- if (next_semaphore_ != NULL) next_semaphore_->Wait(); |
- { |
- v8::Isolate::Scope iscope(isolate); |
- v8::HandleScope scope; |
- v8::Persistent<v8::Context> context = CreateShellContext(); |
- { |
- v8::Context::Scope cscope(context); |
- Execute(); |
- } |
- context.Dispose(); |
- } |
- if (done_semaphore_ != NULL) done_semaphore_->Signal(); |
- } while (!last_run); |
- isolate->Dispose(); |
- } |
- |
- v8::internal::Semaphore* next_semaphore_; |
- v8::internal::Semaphore* done_semaphore_; |
- v8::internal::Thread* thread_; |
-#endif // USING_V8_SHARED |
- |
- const char** argv_; |
- int begin_offset_; |
- int end_offset_; |
-}; |
- |
+static bool run_shell; |
-static SourceGroup* isolate_sources = NULL; |
- |
Yang
2011/07/13 16:08:46
Removed support for compression.
|
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
-class BZip2Decompressor : public v8::StartupDataDecompressor { |
- public: |
- virtual ~BZip2Decompressor() { } |
- |
- protected: |
- virtual int DecompressData(char* raw_data, |
- int* raw_data_size, |
- const char* compressed_data, |
- int compressed_data_size) { |
- ASSERT_EQ(v8::StartupData::kBZip2, |
- v8::V8::GetCompressedStartupDataAlgorithm()); |
- unsigned int decompressed_size = *raw_data_size; |
- int result = |
- BZ2_bzBuffToBuffDecompress(raw_data, |
- &decompressed_size, |
- const_cast<char*>(compressed_data), |
- compressed_data_size, |
- 0, 1); |
- if (result == BZ_OK) { |
- *raw_data_size = decompressed_size; |
- } |
- return result; |
- } |
-}; |
-#endif |
- |
- |
-int RunMain(int argc, char* argv[]) { |
+int main(int argc, char* argv[]) { |
v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
+ run_shell = (argc == 1); |
v8::HandleScope handle_scope; |
v8::Persistent<v8::Context> context = CreateShellContext(); |
- // Enter the newly created execution environment. |
- context->Enter(); |
if (context.IsEmpty()) { |
printf("Error creating context\n"); |
return 1; |
} |
- |
- bool run_shell = (argc == 1); |
- int num_isolates = 1; |
- for (int i = 1; i < argc; i++) { |
- if (strcmp(argv[i], "--isolate") == 0) { |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- ++num_isolates; |
-#else // USING_V8_SHARED |
- printf("Error: --isolate not supported when linked with shared " |
- "library\n"); |
- ExitShell(1); |
-#endif // USING_V8_SHARED |
- } |
- } |
- if (isolate_sources == NULL) { |
- isolate_sources = new SourceGroup[num_isolates]; |
- SourceGroup* current = isolate_sources; |
- current->Begin(argv, 1); |
- for (int i = 1; i < argc; i++) { |
- const char* str = argv[i]; |
- if (strcmp(str, "--isolate") == 0) { |
- current->End(i); |
- current++; |
- current->Begin(argv, i + 1); |
- } else if (strcmp(str, "--shell") == 0) { |
- run_shell = true; |
- } else if (strcmp(str, "-f") == 0) { |
- // Ignore any -f flags for compatibility with the other stand- |
- // alone JavaScript engines. |
- continue; |
- } else if (strncmp(str, "--", 2) == 0) { |
- printf("Warning: unknown flag %s.\nTry --help for options\n", str); |
- } |
- } |
- current->End(argc); |
- } |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- for (int i = 1; i < num_isolates; ++i) { |
- isolate_sources[i].StartExecuteInThread(); |
- } |
-#endif // USING_V8_SHARED |
- isolate_sources[0].Execute(); |
+ context->Enter(); |
+ int result = RunMain(argc, argv); |
if (run_shell) RunShell(context); |
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) |
- for (int i = 1; i < num_isolates; ++i) { |
- isolate_sources[i].WaitForThread(); |
- } |
-#endif // USING_V8_SHARED |
- if (last_run) { |
- delete[] isolate_sources; |
- isolate_sources = NULL; |
- } |
context->Exit(); |
context.Dispose(); |
- return 0; |
-} |
- |
- |
-int main(int argc, char* argv[]) { |
- // Figure out if we're requested to stress the optimization |
- // infrastructure by running tests multiple times and forcing |
- // optimization in the last run. |
- bool FLAG_stress_opt = false; |
- bool FLAG_stress_deopt = false; |
- for (int i = 0; i < argc; i++) { |
- if (strcmp(argv[i], "--stress-opt") == 0) { |
- FLAG_stress_opt = true; |
- argv[i] = NULL; |
- } else if (strcmp(argv[i], "--stress-deopt") == 0) { |
- FLAG_stress_deopt = true; |
- argv[i] = NULL; |
- } else if (strcmp(argv[i], "--noalways-opt") == 0) { |
- // No support for stressing if we can't use --always-opt. |
- FLAG_stress_opt = false; |
- FLAG_stress_deopt = false; |
- break; |
- } |
- } |
- |
-#ifdef COMPRESS_STARTUP_DATA_BZ2 |
- BZip2Decompressor startup_data_decompressor; |
- int bz2_result = startup_data_decompressor.Decompress(); |
- if (bz2_result != BZ_OK) { |
- fprintf(stderr, "bzip error code: %d\n", bz2_result); |
- exit(1); |
- } |
-#endif |
- |
Yang
2011/07/13 16:08:46
Removed stress runs.
|
- v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
- int result = 0; |
- if (FLAG_stress_opt || FLAG_stress_deopt) { |
- v8::Testing::SetStressRunType(FLAG_stress_opt |
- ? v8::Testing::kStressTypeOpt |
- : v8::Testing::kStressTypeDeopt); |
- int stress_runs = v8::Testing::GetStressRuns(); |
- for (int i = 0; i < stress_runs && result == 0; i++) { |
- printf("============ Stress %d/%d ============\n", |
- i + 1, stress_runs); |
- v8::Testing::PrepareStressRun(i); |
- last_run = (i == stress_runs - 1); |
- result = RunMain(argc, argv); |
- } |
- printf("======== Full Deoptimization =======\n"); |
- v8::Testing::DeoptimizeAll(); |
- } else { |
- result = RunMain(argc, argv); |
- } |
v8::V8::Dispose(); |
- |
return result; |
} |
@@ -386,26 +105,6 @@ v8::Persistent<v8::Context> CreateShellContext() { |
// Bind the 'version' function |
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); |
- // Bind the handlers for external arrays. |
- global->Set(v8::String::New("Int8Array"), |
- v8::FunctionTemplate::New(Int8Array)); |
- global->Set(v8::String::New("Uint8Array"), |
- v8::FunctionTemplate::New(Uint8Array)); |
- global->Set(v8::String::New("Int16Array"), |
- v8::FunctionTemplate::New(Int16Array)); |
- global->Set(v8::String::New("Uint16Array"), |
- v8::FunctionTemplate::New(Uint16Array)); |
- global->Set(v8::String::New("Int32Array"), |
- v8::FunctionTemplate::New(Int32Array)); |
- global->Set(v8::String::New("Uint32Array"), |
- v8::FunctionTemplate::New(Uint32Array)); |
- global->Set(v8::String::New("Float32Array"), |
- v8::FunctionTemplate::New(Float32Array)); |
- global->Set(v8::String::New("Float64Array"), |
- v8::FunctionTemplate::New(Float64Array)); |
- global->Set(v8::String::New("PixelArray"), |
- v8::FunctionTemplate::New(PixelArray)); |
- |
return v8::Context::New(NULL, global); |
} |
@@ -479,7 +178,9 @@ v8::Handle<v8::Value> Quit(const v8::Arguments& args) { |
// If not arguments are given args[0] will yield undefined which |
// converts to the integer value 0. |
int exit_code = args[0]->Int32Value(); |
- ExitShell(exit_code); |
+ fflush(stdout); |
+ fflush(stderr); |
+ exit(exit_code); |
return v8::Undefined(); |
} |
@@ -489,113 +190,6 @@ v8::Handle<v8::Value> Version(const v8::Arguments& args) { |
} |
-void ExternalArrayWeakCallback(v8::Persistent<v8::Value> object, void* data) { |
- free(data); |
- object.Dispose(); |
-} |
- |
- |
-v8::Handle<v8::Value> CreateExternalArray(const v8::Arguments& args, |
- v8::ExternalArrayType type, |
- size_t element_size) { |
- assert(element_size == 1 || |
- element_size == 2 || |
- element_size == 4 || |
- element_size == 8); |
- if (args.Length() != 1) { |
- return v8::ThrowException( |
- v8::String::New("Array constructor needs one parameter.")); |
- } |
- static const int kMaxLength = 0x3fffffff; |
- size_t length = 0; |
- if (args[0]->IsUint32()) { |
- length = args[0]->Uint32Value(); |
- } else if (args[0]->IsNumber()) { |
- double raw_length = args[0]->NumberValue(); |
- if (raw_length < 0) { |
- return v8::ThrowException( |
- v8::String::New("Array length must not be negative.")); |
- } |
- if (raw_length > kMaxLength) { |
- return v8::ThrowException( |
- v8::String::New("Array length exceeds maximum length.")); |
- } |
- length = static_cast<size_t>(raw_length); |
- } else { |
- return v8::ThrowException( |
- v8::String::New("Array length must be a number.")); |
- } |
- if (length > static_cast<size_t>(kMaxLength)) { |
- return v8::ThrowException( |
- v8::String::New("Array length exceeds maximum length.")); |
- } |
- void* data = calloc(length, element_size); |
- if (data == NULL) { |
- return v8::ThrowException(v8::String::New("Memory allocation failed.")); |
- } |
- v8::Handle<v8::Object> array = v8::Object::New(); |
- v8::Persistent<v8::Object> persistent_array = |
- v8::Persistent<v8::Object>::New(array); |
- persistent_array.MakeWeak(data, ExternalArrayWeakCallback); |
- persistent_array.MarkIndependent(); |
- array->SetIndexedPropertiesToExternalArrayData(data, type, length); |
- array->Set(v8::String::New("length"), v8::Int32::New(length), |
- v8::ReadOnly); |
- array->Set(v8::String::New("BYTES_PER_ELEMENT"), |
- v8::Int32::New(element_size)); |
- return array; |
-} |
- |
- |
-v8::Handle<v8::Value> Int8Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); |
-} |
- |
- |
-v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalUnsignedByteArray, |
- sizeof(uint8_t)); |
-} |
- |
- |
-v8::Handle<v8::Value> Int16Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalShortArray, sizeof(int16_t)); |
-} |
- |
- |
-v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalUnsignedShortArray, |
- sizeof(uint16_t)); |
-} |
- |
-v8::Handle<v8::Value> Int32Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalIntArray, sizeof(int32_t)); |
-} |
- |
- |
-v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalUnsignedIntArray, |
- sizeof(uint32_t)); |
-} |
- |
- |
-v8::Handle<v8::Value> Float32Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalFloatArray, |
- sizeof(float)); // NOLINT |
-} |
- |
- |
-v8::Handle<v8::Value> Float64Array(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalDoubleArray, |
- sizeof(double)); // NOLINT |
-} |
- |
- |
-v8::Handle<v8::Value> PixelArray(const v8::Arguments& args) { |
- return CreateExternalArray(args, v8::kExternalPixelArray, sizeof(uint8_t)); |
-} |
- |
- |
// Reads a file into a v8 string. |
v8::Handle<v8::String> ReadFile(const char* name) { |
FILE* file = fopen(name, "rb"); |
@@ -618,9 +212,41 @@ v8::Handle<v8::String> ReadFile(const char* name) { |
} |
+// Process remaining command line arguments and execute files |
+int RunMain(int argc, char* argv[]) { |
+ for (int i = 1; i < argc; i++) { |
+ const char* str = argv[i]; |
+ if (strcmp(str, "--shell") == 0) { |
+ run_shell = true; |
+ } else if (strcmp(str, "-f") == 0) { |
+ // Ignore any -f flags for compatibility with the 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::Handle<v8::String> file_name = v8::String::New("unnamed"); |
+ v8::Handle<v8::String> source = v8::String::New(argv[++i]); |
+ if (!ExecuteString(source, file_name, false, true)) return 1; |
+ } else { |
+ // Use all other arguments as names of files to load and run. |
+ v8::Handle<v8::String> file_name = v8::String::New(str); |
+ v8::Handle<v8::String> source = ReadFile(str); |
+ if (source.IsEmpty()) { |
+ printf("Error reading '%s'\n", str); |
+ continue; |
+ } |
+ if (!ExecuteString(source, file_name, false, true)) return 1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+ |
// The read-eval-execute loop of the shell. |
void RunShell(v8::Handle<v8::Context> context) { |
- printf("V8 version %s\n", v8::V8::GetVersion()); |
+ printf("V8 version %s [sample shell]\n", v8::V8::GetVersion()); |
static const int kBufferSize = 256; |
// Enter the execution environment before evaluating any code. |
v8::Context::Scope context_scope(context); |