Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: src/d8.cc

Issue 7519: Added first shot at a development shell (Closed)
Patch Set: Factored js code out of d8.cc. Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29 #include "d8.h"
30 #include "debug.h"
31 #include "api.h"
32 #include "natives.h"
33
34
35 namespace v8 {
36
37
38 const char* Shell::kHistoryFileName = ".d8_history";
39 const char* Shell::kPrompt = "d8> ";
40
41
42 LineEditor *LineEditor::first_ = NULL;
43
44
45 LineEditor::LineEditor(Type type, const char* name)
46 : type_(type),
47 name_(name),
48 next_(first_) {
49 first_ = this;
50 }
51
52
53 LineEditor* LineEditor::Get() {
54 LineEditor* current = first_;
55 LineEditor* best = current;
56 while (current != NULL) {
57 if (current->type_ > best->type_)
58 best = current;
59 current = current->next_;
60 }
61 return best;
62 }
63
64
65 class DumbLineEditor: public LineEditor {
66 public:
67 DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
68 virtual i::SmartPointer<char> Prompt(const char* prompt);
69 };
70
71
72 static DumbLineEditor dumb_line_editor;
73
74
75 i::SmartPointer<char> DumbLineEditor::Prompt(const char* prompt) {
76 static const int kBufferSize = 256;
77 char buffer[kBufferSize];
78 printf("%s", prompt);
79 char* str = fgets(buffer, kBufferSize, stdin);
80 return i::SmartPointer<char>(str ? i::OS::StrDup(str) : str);
81 }
82
83
84 Shell::CounterMap Shell::counter_map_;
85 Persistent<Context> Shell::utility_context_;
86 Persistent<Context> Shell::evaluation_context_;
87
88
89 // Executes a string within the current v8 context.
90 bool Shell::ExecuteString(Handle<String> source,
91 Handle<Value> name,
92 bool print_result,
93 bool report_exceptions) {
94 HandleScope handle_scope;
95 TryCatch try_catch;
96 Handle<Script> script = Script::Compile(source, name);
97 if (script.IsEmpty()) {
98 // Print errors that happened during compilation.
99 if (report_exceptions)
100 ReportException(&try_catch);
101 return false;
102 } else {
103 Handle<Value> result = script->Run();
104 if (result.IsEmpty()) {
105 // Print errors that happened during execution.
106 if (report_exceptions)
107 ReportException(&try_catch);
108 return false;
109 } else {
110 if (print_result && !result->IsUndefined()) {
111 // If all went well and the result wasn't undefined then print
112 // the returned value.
113 String::Utf8Value str(result);
114 printf("%s\n", *str);
115 }
116 return true;
117 }
118 }
119 }
120
121
122 Handle<Value> Shell::Print(const Arguments& args) {
123 bool first = true;
124 for (int i = 0; i < args.Length(); i++) {
125 HandleScope handle_scope;
126 if (first) {
127 first = false;
128 } else {
129 printf(" ");
130 }
131 String::Utf8Value str(args[i]);
132 printf("%s", *str);
133 }
134 printf("\n");
135 return Undefined();
136 }
137
138
139 Handle<Value> Shell::Load(const Arguments& args) {
140 for (int i = 0; i < args.Length(); i++) {
141 HandleScope handle_scope;
142 String::Utf8Value file(args[i]);
143 Handle<String> source = ReadFile(*file);
144 if (source.IsEmpty()) {
145 return ThrowException(String::New("Error loading file"));
146 }
147 if (!ExecuteString(source, String::New(*file), false, false)) {
148 return ThrowException(String::New("Error executing file"));
149 }
150 }
151 return Undefined();
152 }
153
154
155 Handle<Value> Shell::Quit(const Arguments& args) {
156 int exit_code = args[0]->Int32Value();
157 OnExit();
158 exit(exit_code);
159 return Undefined();
160 }
161
162
163 Handle<Value> Shell::Version(const Arguments& args) {
164 return String::New(V8::GetVersion());
165 }
166
167
168 void Shell::ReportException(v8::TryCatch* try_catch) {
169 HandleScope handle_scope;
170 String::Utf8Value exception(try_catch->Exception());
171 Handle<Message> message = try_catch->Message();
172 if (message.IsEmpty()) {
173 // V8 didn't provide any extra information about this error; just
174 // print the exception.
175 printf("%s\n", *exception);
176 } else {
177 // Print (filename):(line number): (message).
178 String::Utf8Value filename(message->GetScriptResourceName());
179 int linenum = message->GetLineNumber();
180 printf("%s:%i: %s\n", *filename, linenum, *exception);
181 // Print line of source code.
182 String::Utf8Value sourceline(message->GetSourceLine());
183 printf("%s\n", *sourceline);
184 // Print wavy underline (GetUnderline is deprecated).
185 int start = message->GetStartColumn();
186 for (int i = 0; i < start; i++) {
187 printf(" ");
188 }
189 int end = message->GetEndColumn();
190 for (int i = start; i < end; i++) {
191 printf("^");
192 }
193 printf("\n");
194 }
195 }
196
197
198 Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
199 HandleScope handle_scope;
200 Context::Scope context_scope(utility_context_);
201 Handle<Object> global = utility_context_->Global();
202 Handle<Value> fun = global->Get(String::New("GetCompletions"));
203 static const int kArgc = 3;
204 Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
205 Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
206 return handle_scope.Close(Handle<Array>::Cast(val));
207 }
208
209
210 int* Shell::LookupCounter(const wchar_t* name) {
211 CounterMap::iterator item = counter_map_.find(name);
212 if (item != counter_map_.end()) {
213 Counter* result = (*item).second;
214 return result->GetValuePtr();
215 }
216 Counter* result = new Counter(name);
217 counter_map_[name] = result;
218 return result->GetValuePtr();
219 }
220
221
222 void Shell::Initialize() {
223 // Set up counters
224 if (i::FLAG_dump_counters)
225 V8::SetCounterFunction(LookupCounter);
226 // Initialize the global objects
227 HandleScope scope;
228 Handle<ObjectTemplate> global_template = ObjectTemplate::New();
229 global_template->Set(String::New("print"), FunctionTemplate::New(Print));
230 global_template->Set(String::New("load"), FunctionTemplate::New(Load));
231 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
232 global_template->Set(String::New("version"), FunctionTemplate::New(Version));
233
234 utility_context_ = Context::New(NULL, global_template);
235 utility_context_->SetSecurityToken(Undefined());
236 Context::Scope utility_scope(utility_context_);
237
238 // Install the debugger object in the utility scope
239 i::Debug::Load();
240 i::JSObject* raw_debug = i::Debug::debug_context()->global();
241 i::JSGlobalObject* debug = i::JSGlobalObject::cast(raw_debug);
242 debug->set_security_token(i::Heap::undefined_value());
243 utility_context_->Global()->Set(String::New("$debug"),
244 Utils::ToLocal(&raw_debug));
245
246 // Run the d8 shell utility script in the utility context
247 int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
248 i::Vector<const char> shell_source
249 = i::NativesCollection<i::D8>::GetScriptSource(source_index);
250 i::Vector<const char> shell_source_name
251 = i::NativesCollection<i::D8>::GetScriptName(source_index);
252 Handle<String> source = String::New(shell_source.start(),
253 shell_source.length());
254 Handle<String> name = String::New(shell_source_name.start(),
255 shell_source_name.length());
256 Script::Compile(source, name)->Run();
257
258 // Create the evaluation context
259 evaluation_context_ = Context::New(NULL, global_template);
260 evaluation_context_->SetSecurityToken(Undefined());
261 }
262
263
264 void Shell::OnExit() {
265 if (i::FLAG_dump_counters) {
266 ::printf("+----------------------------------------+----------+\n");
267 ::printf("| Name | Value |\n");
268 ::printf("+----------------------------------------+----------+\n");
269 for (CounterMap::iterator i = counter_map_.begin();
270 i != counter_map_.end();
271 i++) {
272 Counter* counter = (*i).second;
273 ::printf("| %-38ls | %8i |\n", counter->name(), counter->value());
274 }
275 ::printf("+----------------------------------------+----------+\n");
276 }
277 }
278
279
280 // Reads a file into a v8 string.
281 Handle<String> Shell::ReadFile(const char* name) {
282 FILE* file = i::OS::FOpen(name, "rb");
283 if (file == NULL) return Handle<String>();
284
285 fseek(file, 0, SEEK_END);
286 int size = ftell(file);
287 rewind(file);
288
289 char* chars = new char[size + 1];
290 chars[size] = '\0';
291 for (int i = 0; i < size;) {
292 int read = fread(&chars[i], 1, size - i, file);
293 i += read;
294 }
295 fclose(file);
296 Handle<String> result = String::New(chars, size);
297 delete[] chars;
298 return result;
299 }
300
301
302 void Shell::RunShell() {
303 LineEditor* editor = LineEditor::Get();
304 printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
305 editor->Open();
306 while (true) {
307 HandleScope handle_scope;
308 i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
309 if (input.is_empty())
310 break;
311 editor->AddHistory(*input);
312 Handle<String> name = String::New("(d8)");
313 ExecuteString(String::New(*input), name, true, true);
314 }
315 editor->Close();
316 printf("\n");
317 }
318
319
320 int Shell::Main(int argc, char* argv[]) {
321 i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
322 Initialize();
323 bool run_shell = (argc == 1);
324 Context::Scope context_scope(evaluation_context_);
325 for (int i = 1; i < argc; i++) {
326 char* str = argv[i];
327 HandleScope handle_scope;
328 Handle<String> file_name = v8::String::New(str);
329 Handle<String> source = ReadFile(str);
330 if (source.IsEmpty()) {
331 printf("Error reading '%s'\n", str);
332 return 1;
333 }
334 if (!ExecuteString(source, file_name, false, true))
335 return 1;
336 }
337 if (run_shell)
338 RunShell();
339 OnExit();
340 return 0;
341 }
342 } // v8
343
344
345 int main(int argc, char* argv[]) {
346 return v8::Shell::Main(argc, argv);
347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698