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

Side by Side Diff: src/d8.js

Issue 14195: Added command line debugger to D8 shell.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years 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 | Annotate | Revision Log
« no previous file with comments | « src/d8.cc ('k') | src/d8-debug.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 // How crappy is it that I have to implement completely basic stuff 28 // How crappy is it that I have to implement completely basic stuff
29 // like this myself? Answer: very. 29 // like this myself? Answer: very.
30 String.prototype.startsWith = function (str) { 30 String.prototype.startsWith = function (str) {
31 if (str.length > this.length) 31 if (str.length > this.length)
32 return false; 32 return false;
33 return this.substr(0, str.length) == str; 33 return this.substr(0, str.length) == str;
34 }; 34 }
35
36 function log10(num) {
37 return Math.log(num)/Math.log(10);
38 }
35 39
36 function ToInspectableObject(obj) { 40 function ToInspectableObject(obj) {
37 if (!obj && typeof obj === 'object') { 41 if (!obj && typeof obj === 'object') {
38 return void 0; 42 return void 0;
39 } else { 43 } else {
40 return Object(obj); 44 return Object(obj);
41 } 45 }
42 } 46 }
43 47
44 function GetCompletions(global, last, full) { 48 function GetCompletions(global, last, full) {
(...skipping 16 matching lines...) Expand all
61 var properties = mirror.properties(); 65 var properties = mirror.properties();
62 for (var i = 0; i < properties.length; i++) { 66 for (var i = 0; i < properties.length; i++) {
63 var name = properties[i].name(); 67 var name = properties[i].name();
64 if (typeof name === 'string' && name.startsWith(last)) 68 if (typeof name === 'string' && name.startsWith(last))
65 result.push(name); 69 result.push(name);
66 } 70 }
67 current = ToInspectableObject(current.__proto__); 71 current = ToInspectableObject(current.__proto__);
68 } 72 }
69 return result; 73 return result;
70 } 74 }
75
76
77 // Global object holding debugger related constants and state.
78 const Debug = {};
79
80
81 // Debug events which can occour in the V8 JavaScript engine. These originate
82 // from the API include file debug.h.
83 Debug.DebugEvent = { Break: 1,
84 Exception: 2,
85 NewFunction: 3,
86 BeforeCompile: 4,
87 AfterCompile: 5 };
88
89
90 // The different types of scripts matching enum ScriptType in objects.h.
91 Debug.ScriptType = { Native: 0,
92 Extension: 1,
93 Normal: 2 };
94
95
96 // Current debug state.
97 const kNoFrame = -1;
98 Debug.State = {
99 currentFrame: kNoFrame,
100 currentSourceLine: -1
101 }
102
103
104 function DebugEventToText(event) {
105 if (event.eventType() == 1) {
106 // Build the break details.
107 var details = '';
108 if (event.breakPointsHit()) {
109 details += 'breakpoint';
110 if (event.breakPointsHit().length > 1) {
111 details += 's';
112 }
113 details += ' #';
114 for (var i = 0; i < event.breakPointsHit().length; i++) {
115 if (i > 0) {
116 details += ', #';
117 }
118 // Find the break point number. For break points originating from a
119 // script break point display the script break point number.
120 var break_point = event.breakPointsHit()[i];
121 var script_break_point = break_point.script_break_point();
122 if (script_break_point) {
123 details += script_break_point.number();
124 } else {
125 details += break_point.number();
126 }
127 }
128 } else {
129 details += 'break';
130 }
131 details += ' in ';
132 details += event.executionState().frame(0).invocationText();
133 details += ' at ';
134 details += event.executionState().frame(0).sourceAndPositionText();
135 details += '\n'
136 if (event.func().script()) {
137 details += FrameSourceUnderline(event.executionState().frame(0));
138 }
139 Debug.State.currentSourceLine =
140 event.executionState().frame(0).sourceLine();
141 Debug.State.currentFrame = 0;
142 return details;
143 } else if (event.eventType() == 2) {
144 var details = '';
145 if (event.uncaught_) {
146 details += 'Uncaught: ';
147 } else {
148 details += 'Exception: ';
149 }
150
151 details += '"';
152 details += event.exception();
153 details += '"';
154 if (event.executionState().frameCount() > 0) {
155 details += '"';
156 details += event.exception();
157 details += ' at ';
158 details += event.executionState().frame(0).sourceAndPositionText();
159 details += '\n';
160 details += FrameSourceUnderline(event.executionState().frame(0));
161 Debug.State.currentSourceLine =
162 event.executionState().frame(0).sourceLine();
163 Debug.State.currentFrame = 0;
164 } else {
165 details += ' (empty stack)';
166 Debug.State.currentSourceLine = -1;
167 Debug.State.currentFrame = kNoFrame;
168 }
169
170 return details;
171 }
172
173 return 'Unknown debug event ' + event.eventType();
174 };
175
176
177 function SourceUnderline(source_text, position) {
178 if (!source_text) {
179 return;
180 }
181
182 // Create an underline with a caret pointing to the source position. If the
183 // source contains a tab character the underline will have a tab character in
184 // the same place otherwise the underline will have a space character.
185 var underline = '';
186 for (var i = 0; i < position; i++) {
187 if (source_text[i] == '\t') {
188 underline += '\t';
189 } else {
190 underline += ' ';
191 }
192 }
193 underline += '^';
194
195 // Return the source line text with the underline beneath.
196 return source_text + '\n' + underline;
197 };
198
199
200 function FrameSourceUnderline(frame) {
201 var location = frame.sourceLocation();
202 if (location) {
203 return SourceUnderline(location.sourceText(), location.position - location.s tart);
204 }
205 };
206
207
208 // Converts a text command to a JSON request.
209 function DebugCommandToJSONRequest(cmd_line) {
210 return new DebugRequest(cmd_line).JSONRequest();
211 };
212
213
214 function DebugRequest(cmd_line) {
215 // If the very first character is a { assume that a JSON request have been
216 // entered as a command. Converting that to a JSON request is trivial.
217 if (cmd_line && cmd_line.length > 0 && cmd_line.charAt(0) == '{') {
218 this.request_ = cmd_line;
219 return;
220 }
221
222 // Trim string for leading and trailing whitespace.
223 cmd_line = cmd_line.replace(/^\s+|\s+$/g, '');
224
225 // Find the command.
226 var pos = cmd_line.indexOf(' ');
227 var cmd;
228 var args;
229 if (pos == -1) {
230 cmd = cmd_line;
231 args = '';
232 } else {
233 cmd = cmd_line.slice(0, pos);
234 args = cmd_line.slice(pos).replace(/^\s+|\s+$/g, '');
235 }
236
237 // Switch on command.
238 if (cmd == 'continue' || cmd == 'c') {
239 this.request_ = this.continueCommandToJSONRequest_(args);
240 } else if (cmd == 'step' || cmd == 's') {
241 this.request_ = this.stepCommandToJSONRequest_(args);
242 } else if (cmd == 'backtrace' || cmd == 'bt') {
243 this.request_ = this.backtraceCommandToJSONRequest_(args);
244 } else if (cmd == 'frame' || cmd == 'f') {
245 this.request_ = this.frameCommandToJSONRequest_(args);
246 } else if (cmd == 'print' || cmd == 'p') {
247 this.request_ = this.printCommandToJSONRequest_(args);
248 } else if (cmd == 'source') {
249 this.request_ = this.sourceCommandToJSONRequest_(args);
250 } else if (cmd == 'scripts') {
251 this.request_ = this.scriptsCommandToJSONRequest_(args);
252 } else if (cmd == 'break' || cmd == 'b') {
253 this.request_ = this.breakCommandToJSONRequest_(args);
254 } else if (cmd == 'clear') {
255 this.request_ = this.clearCommandToJSONRequest_(args);
256 } else if (cmd == 'help' || cmd == '?') {
257 this.helpCommand_(args);
258 // Return null to indicate no JSON to send (command handled internally).
259 this.request_ = void 0;
260 } else {
261 throw new Error('Unknown command "' + cmd + '"');
262 }
263 }
264
265 DebugRequest.prototype.JSONRequest = function() {
266 return this.request_;
267 }
268
269
270 function RequestPacket(command) {
271 this.seq = 0;
272 this.type = 'request';
273 this.command = command;
274 }
275
276
277 RequestPacket.prototype.toJSONProtocol = function() {
278 // Encode the protocol header.
279 var json = '{';
280 json += '"seq":' + this.seq;
281 json += ',"type":"' + this.type + '"';
282 if (this.command) {
283 json += ',"command":' + StringToJSON_(this.command);
284 }
285 if (this.arguments) {
286 json += ',"arguments":';
287 // Encode the arguments part.
288 if (this.arguments.toJSONProtocol) {
289 json += this.arguments.toJSONProtocol()
290 } else {
291 json += SimpleObjectToJSON_(this.arguments);
292 }
293 }
294 json += '}';
295 return json;
296 }
297
298
299 DebugRequest.prototype.createRequest = function(command) {
300 return new RequestPacket(command);
301 };
302
303
304 // Create a JSON request for the continue command.
305 DebugRequest.prototype.continueCommandToJSONRequest_ = function(args) {
306 var request = this.createRequest('continue');
307 return request.toJSONProtocol();
308 };
309
310
311 // Create a JSON request for the step command.
312 DebugRequest.prototype.stepCommandToJSONRequest_ = function(args) {
313 // Requesting a step is through the continue command with additional
314 // arguments.
315 var request = this.createRequest('continue');
316 request.arguments = {};
317
318 // Process arguments if any.
319 if (args && args.length > 0) {
320 args = args.split(/\s*[ ]+\s*/g);
321
322 if (args.length > 2) {
323 throw new Error('Invalid step arguments.');
324 }
325
326 if (args.length > 0) {
327 // Get step count argument if any.
328 if (args.length == 2) {
329 var stepcount = parseInt(args[1]);
330 if (isNaN(stepcount) || stepcount <= 0) {
331 throw new Error('Invalid step count argument "' + args[0] + '".');
332 }
333 request.arguments.stepcount = stepcount;
334 }
335
336 // Get the step action.
337 if (args[0] == 'in' || args[0] == 'i') {
338 request.arguments.stepaction = 'in';
339 } else if (args[0] == 'min' || args[0] == 'm') {
340 request.arguments.stepaction = 'min';
341 } else if (args[0] == 'next' || args[0] == 'n') {
342 request.arguments.stepaction = 'next';
343 } else if (args[0] == 'out' || args[0] == 'o') {
344 request.arguments.stepaction = 'out';
345 } else {
346 throw new Error('Invalid step argument "' + args[0] + '".');
347 }
348 }
349 } else {
350 // Default is step next.
351 request.arguments.stepaction = 'next';
352 }
353
354 return request.toJSONProtocol();
355 };
356
357
358 // Create a JSON request for the backtrace command.
359 DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) {
360 // Build a backtrace request from the text command.
361 var request = this.createRequest('backtrace');
362 args = args.split(/\s*[ ]+\s*/g);
363 if (args.length == 2) {
364 request.arguments = {};
365 var fromFrame = parseInt(args[0]);
366 var toFrame = parseInt(args[1]);
367 if (isNaN(fromFrame) || fromFrame < 0) {
368 throw new Error('Invalid start frame argument "' + args[0] + '".');
369 }
370 if (isNaN(toFrame) || toFrame < 0) {
371 throw new Error('Invalid end frame argument "' + args[1] + '".');
372 }
373 if (fromFrame > toFrame) {
374 throw new Error('Invalid arguments start frame cannot be larger ' +
375 'than end frame.');
376 }
377 request.arguments.fromFrame = fromFrame;
378 request.arguments.toFrame = toFrame + 1;
379 }
380 return request.toJSONProtocol();
381 };
382
383
384 // Create a JSON request for the frame command.
385 DebugRequest.prototype.frameCommandToJSONRequest_ = function(args) {
386 // Build a frame request from the text command.
387 var request = this.createRequest('frame');
388 args = args.split(/\s*[ ]+\s*/g);
389 if (args.length > 0 && args[0].length > 0) {
390 request.arguments = {};
391 request.arguments.number = args[0];
392 }
393 return request.toJSONProtocol();
394 };
395
396
397 // Create a JSON request for the print command.
398 DebugRequest.prototype.printCommandToJSONRequest_ = function(args) {
399 // Build a evaluate request from the text command.
400 var request = this.createRequest('evaluate');
401 if (args.length == 0) {
402 throw new Error('Missing expression.');
403 }
404
405 request.arguments = {};
406 request.arguments.expression = args;
407
408 return request.toJSONProtocol();
409 };
410
411
412 // Create a JSON request for the source command.
413 DebugRequest.prototype.sourceCommandToJSONRequest_ = function(args) {
414 // Build a evaluate request from the text command.
415 var request = this.createRequest('source');
416
417 // Default is ten lines starting five lines before the current location.
418 var from = Debug.State.currentSourceLine - 5;
419 var lines = 10;
420
421 // Parse the arguments.
422 args = args.split(/\s*[ ]+\s*/g);
423 if (args.length > 1 && args[0].length > 0 && args[1].length > 0) {
424 from = parseInt(args[0]) - 1;
425 lines = parseInt(args[1]);
426 } else if (args.length > 0 && args[0].length > 0) {
427 from = parseInt(args[0]) - 1;
428 }
429
430 if (from < 0) from = 0;
431 if (lines < 0) lines = 10;
432
433 // Request source arround current source location.
434 request.arguments = {};
435 request.arguments.fromLine = from;
436 request.arguments.toLine = from + lines;
437
438 return request.toJSONProtocol();
439 };
440
441
442 // Create a JSON request for the scripts command.
443 DebugRequest.prototype.scriptsCommandToJSONRequest_ = function(args) {
444 // Build a evaluate request from the text command.
445 var request = this.createRequest('scripts');
446
447 // Process arguments if any.
448 if (args && args.length > 0) {
449 args = args.split(/\s*[ ]+\s*/g);
450
451 if (args.length > 1) {
452 throw new Error('Invalid scripts arguments.');
453 }
454
455 request.arguments = {};
456 if (args[0] == 'natives') {
457 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Native);
458 } else if (args[0] == 'extensions') {
459 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Extension);
460 } else if (args[0] == 'all') {
461 request.arguments.types =
462 ScriptTypeFlag(Debug.ScriptType.Normal) |
463 ScriptTypeFlag(Debug.ScriptType.Native) |
464 ScriptTypeFlag(Debug.ScriptType.Extension);
465 } else {
466 throw new Error('Invalid argument "' + args[0] + '".');
467 }
468 }
469
470 return request.toJSONProtocol();
471 };
472
473
474 // Create a JSON request for the break command.
475 DebugRequest.prototype.breakCommandToJSONRequest_ = function(args) {
476 // Build a evaluate request from the text command.
477 var request = this.createRequest('setbreakpoint');
478
479 // Process arguments if any.
480 if (args && args.length > 0) {
481 var target = args;
482 var condition;
483
484 var pos = args.indexOf(' ');
485 if (pos > 0) {
486 target = args.substring(0, pos);
487 condition = args.substring(pos + 1, args.length);
488 }
489
490 request.arguments = {};
491 request.arguments.type = 'function';
492 request.arguments.target = target;
493 request.arguments.condition = condition;
494 } else {
495 throw new Error('Invalid break arguments.');
496 }
497
498 return request.toJSONProtocol();
499 };
500
501
502 // Create a JSON request for the clear command.
503 DebugRequest.prototype.clearCommandToJSONRequest_ = function(args) {
504 // Build a evaluate request from the text command.
505 var request = this.createRequest('clearbreakpoint');
506
507 // Process arguments if any.
508 if (args && args.length > 0) {
509 request.arguments = {};
510 request.arguments.breakpoint = parseInt(args);
511 } else {
512 throw new Error('Invalid break arguments.');
513 }
514
515 return request.toJSONProtocol();
516 };
517
518
519 // Create a JSON request for the break command.
520 DebugRequest.prototype.helpCommand_ = function(args) {
521 // Help os quite simple.
522 if (args && args.length > 0) {
523 print('warning: arguments to \'help\' are ignored');
524 }
525
526 print('break location [condition]');
527 print('clear <breakpoint #>');
528 print('backtrace [from frame #] [to frame #]]');
529 print('frame <frame #>');
530 print('step [in | next | out| min [step count]]');
531 print('print <expression>');
532 print('source [from line [num lines]]');
533 print('scripts');
534 print('continue');
535 print('help');
536 }
537
538
539 // Convert a JSON response to text for display in a text based debugger.
540 function DebugResponseDetails(json_response) {
541 details = {text:'', running:false}
542
543 try {
544 // Convert the JSON string to an object.
545 response = eval('(' + json_response + ')');
546
547 if (!response.success) {
548 details.text = response.message;
549 return details;
550 }
551
552 // Get the running state.
553 details.running = response.running;
554
555 if (response.command == 'setbreakpoint') {
556 var body = response.body;
557 result = 'set breakpoint #';
558 result += body.breakpoint;
559 details.text = result;
560 } else if (response.command == 'clearbreakpoint') {
561 var body = response.body;
562 result = 'cleared breakpoint #';
563 result += body.breakpoint;
564 details.text = result;
565 } else if (response.command == 'backtrace') {
566 var body = response.body;
567 if (body.totalFrames == 0) {
568 result = '(empty stack)';
569 } else {
570 var result = 'Frames #' + body.fromFrame + ' to #' +
571 (body.toFrame - 1) + ' of ' + body.totalFrames + '\n';
572 for (i = 0; i < body.frames.length; i++) {
573 if (i != 0) result += '\n';
574 result += body.frames[i].text;
575 }
576 }
577 details.text = result;
578 } else if (response.command == 'frame') {
579 details.text = SourceUnderline(response.body.sourceLineText,
580 response.body.column);
581 Debug.State.currentSourceLine = response.body.line;
582 Debug.State.currentFrame = response.body.index;
583 } else if (response.command == 'evaluate') {
584 details.text = response.body.text;
585 } else if (response.command == 'source') {
586 // Get the source from the response.
587 var source = response.body.source;
588 var from_line = response.body.fromLine + 1;
589 var lines = source.split('\n');
590 var maxdigits = 1 + Math.floor(log10(from_line + lines.length));
591 if (maxdigits < 3) {
592 maxdigits = 3;
593 }
594 var result = '';
595 for (var num = 0; num < lines.length; num++) {
596 // Check if there's an extra newline at the end.
597 if (num == (lines.length - 1) && lines[num].length == 0) {
598 break;
599 }
600
601 var current_line = from_line + num;
602 spacer = maxdigits - (1 + Math.floor(log10(current_line)));
603 if (current_line == Debug.State.currentSourceLine + 1) {
604 for (var i = 0; i < maxdigits; i++) {
605 result += '>';
606 }
607 result += ' ';
608 } else {
609 for (var i = 0; i < spacer; i++) {
610 result += ' ';
611 }
612 result += current_line + ': ';
613 }
614 result += lines[num];
615 result += '\n';
616 }
617 details.text = result;
618 } else if (response.command == 'scripts') {
619 var result = '';
620 for (i = 0; i < response.body.length; i++) {
621 if (i != 0) result += '\n';
622 if (response.body[i].name) {
623 result += response.body[i].name;
624 } else {
625 result += '[unnamed] ';
626 var sourceStart = response.body[i].sourceStart;
627 if (sourceStart.length > 40) {
628 sourceStart = sourceStart.substring(0, 37) + '...';
629 }
630 result += sourceStart;
631 }
632 result += ' (lines: ';
633 result += response.body[i].sourceLines;
634 result += ', length: ';
635 result += response.body[i].sourceLength;
636 if (response.body[i].type == Debug.ScriptType.Native) {
637 result += ', native';
638 } else if (response.body[i].type == Debug.ScriptType.Extension) {
639 result += ', extension';
640 }
641 result += ')';
642 }
643 details.text = result;
644 }
645 } catch (e) {
646 details.text = 'Error: "' + e + '" formatting response';
647 }
648
649 return details;
650 };
651
652
653 function MakeJSONPair_(name, value) {
654 return '"' + name + '":' + value;
655 }
656
657
658 function ArrayToJSONObject_(content) {
659 return '{' + content.join(',') + '}';
660 }
661
662
663 function ArrayToJSONArray_(content) {
664 return '[' + content.join(',') + ']';
665 }
666
667
668 function BooleanToJSON_(value) {
669 return String(value);
670 }
671
672
673 function NumberToJSON_(value) {
674 return String(value);
675 }
676
677
678 // Mapping of some control characters to avoid the \uXXXX syntax for most
679 // commonly used control cahracters.
680 const ctrlCharMap_ = {
681 '\b': '\\b',
682 '\t': '\\t',
683 '\n': '\\n',
684 '\f': '\\f',
685 '\r': '\\r',
686 '"' : '\\"',
687 '\\': '\\\\'
688 };
689
690
691 // Regular expression testing for ", \ and control characters (0x00 - 0x1F).
692 const ctrlCharTest_ = new RegExp('["\\\\\x00-\x1F]');
693
694
695 // Regular expression matching ", \ and control characters (0x00 - 0x1F)
696 // globally.
697 const ctrlCharMatch_ = new RegExp('["\\\\\x00-\x1F]', 'g');
698
699
700 /**
701 * Convert a String to its JSON representation (see http://www.json.org/). To
702 * avoid depending on the String object this method calls the functions in
703 * string.js directly and not through the value.
704 * @param {String} value The String value to format as JSON
705 * @return {string} JSON formatted String value
706 */
707 function StringToJSON_(value) {
708 // Check for" , \ and control characters (0x00 - 0x1F). No need to call
709 // RegExpTest as ctrlchar is constructed using RegExp.
710 if (ctrlCharTest_.test(value)) {
711 // Replace ", \ and control characters (0x00 - 0x1F).
712 return '"' +
713 value.replace(ctrlCharMatch_, function (char) {
714 // Use charmap if possible.
715 var mapped = ctrlCharMap_[char];
716 if (mapped) return mapped;
717 mapped = char.charCodeAt();
718 // Convert control character to unicode escape sequence.
719 return '\\u00' +
720 '0' + // TODO %NumberToRadixString(Math.floor(mapped / 16), 16) +
721 '0' // TODO %NumberToRadixString(mapped % 16, 16);
722 })
723 + '"';
724 }
725
726 // Simple string with no special characters.
727 return '"' + value + '"';
728 }
729
730
731 /**
732 * Convert a Date to ISO 8601 format. To avoid depending on the Date object
733 * this method calls the functions in date.js directly and not through the
734 * value.
735 * @param {Date} value The Date value to format as JSON
736 * @return {string} JSON formatted Date value
737 */
738 function DateToISO8601_(value) {
739 function f(n) {
740 return n < 10 ? '0' + n : n;
741 }
742 function g(n) {
743 return n < 10 ? '00' + n : n < 100 ? '0' + n : n;
744 }
745 return builtins.GetUTCFullYearFrom(value) + '-' +
746 f(builtins.GetUTCMonthFrom(value) + 1) + '-' +
747 f(builtins.GetUTCDateFrom(value)) + 'T' +
748 f(builtins.GetUTCHoursFrom(value)) + ':' +
749 f(builtins.GetUTCMinutesFrom(value)) + ':' +
750 f(builtins.GetUTCSecondsFrom(value)) + '.' +
751 g(builtins.GetUTCMillisecondsFrom(value)) + 'Z';
752 }
753
754
755 /**
756 * Convert a Date to ISO 8601 format. To avoid depending on the Date object
757 * this method calls the functions in date.js directly and not through the
758 * value.
759 * @param {Date} value The Date value to format as JSON
760 * @return {string} JSON formatted Date value
761 */
762 function DateToJSON_(value) {
763 return '"' + DateToISO8601_(value) + '"';
764 }
765
766
767 /**
768 * Convert an Object to its JSON representation (see http://www.json.org/).
769 * This implementation simply runs through all string property names and adds
770 * each property to the JSON representation for some predefined types. For type
771 * "object" the function calls itself recursively unless the object has the
772 * function property "toJSONProtocol" in which case that is used. This is not
773 * a general implementation but sufficient for the debugger. Note that circular
774 * structures will cause infinite recursion.
775 * @param {Object} object The object to format as JSON
776 * @return {string} JSON formatted object value
777 */
778 function SimpleObjectToJSON_(object) {
779 var content = [];
780 for (var key in object) {
781 // Only consider string keys.
782 if (typeof key == 'string') {
783 var property_value = object[key];
784
785 // Format the value based on its type.
786 var property_value_json;
787 switch (typeof property_value) {
788 case 'object':
789 if (typeof property_value.toJSONProtocol == 'function') {
790 property_value_json = property_value.toJSONProtocol(true)
791 } else if (property_value.constructor.name == 'Array'){
792 property_value_json = SimpleArrayToJSON_(property_value);
793 } else {
794 property_value_json = SimpleObjectToJSON_(property_value);
795 }
796 break;
797
798 case 'boolean':
799 property_value_json = BooleanToJSON_(property_value);
800 break;
801
802 case 'number':
803 property_value_json = NumberToJSON_(property_value);
804 break;
805
806 case 'string':
807 property_value_json = StringToJSON_(property_value);
808 break;
809
810 default:
811 property_value_json = null;
812 }
813
814 // Add the property if relevant.
815 if (property_value_json) {
816 content.push(StringToJSON_(key) + ':' + property_value_json);
817 }
818 }
819 }
820
821 // Make JSON object representation.
822 return '{' + content.join(',') + '}';
823 }
824
825
826 /**
827 * Convert an array to its JSON representation. This is a VERY simple
828 * implementation just to support what is needed for the debugger.
829 * @param {Array} arrya The array to format as JSON
830 * @return {string} JSON formatted array value
831 */
832 function SimpleArrayToJSON_(array) {
833 // Make JSON array representation.
834 var json = '[';
835 for (var i = 0; i < array.length; i++) {
836 if (i != 0) {
837 json += ',';
838 }
839 var elem = array[i];
840 if (elem.toJSONProtocol) {
841 json += elem.toJSONProtocol(true)
842 } else if (typeof(elem) === 'object') {
843 json += SimpleObjectToJSON_(elem);
844 } else if (typeof(elem) === 'boolean') {
845 json += BooleanToJSON_(elem);
846 } else if (typeof(elem) === 'number') {
847 json += NumberToJSON_(elem);
848 } else if (typeof(elem) === 'string') {
849 json += StringToJSON_(elem);
850 } else {
851 json += elem;
852 }
853 }
854 json += ']';
855 return json;
856 }
OLDNEW
« no previous file with comments | « src/d8.cc ('k') | src/d8-debug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698