explorer.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. var repl = require('repl');
  2. var debuggerCommons = require('../debuggerCommons');
  3. var CommandRepl = require('../modes/commandRepl');
  4. /**
  5. * BETA BETA BETA
  6. * Custom explorer to test protractor commands.
  7. *
  8. * @constructor
  9. */
  10. var WdRepl = function() {
  11. this.client;
  12. };
  13. /**
  14. * Instantiate a server to handle IO.
  15. * @param {number} port The port to start the server.
  16. * @private
  17. */
  18. WdRepl.prototype.initServer_ = function(port) {
  19. var net = require('net');
  20. var self = this;
  21. var cmdRepl = new CommandRepl(this.client);
  22. var received = '';
  23. net.createServer(function(sock) {
  24. sock.on('data', function(data) {
  25. received += data.toString();
  26. var eolIndex = received.indexOf('\r\n');
  27. if (eolIndex === 0) {
  28. return;
  29. }
  30. var input = received.substring(0, eolIndex);
  31. received = received.substring(eolIndex + 2);
  32. if (data[0] === 0x1D) {
  33. // '^]': term command
  34. self.client.req({command: 'disconnect'}, function() {
  35. // Intentionally blank.
  36. });
  37. sock.end();
  38. // TODO(juliemr): Investigate why this is necessary. At this point, there
  39. // should be no active listeners so this process should just exit
  40. // by itself.
  41. process.exit(0);
  42. } else if (input[input.length - 1] === '\t') {
  43. // If the last character is the TAB key, this is an autocomplete
  44. // request. We use everything before the TAB as the init data to feed
  45. // into autocomplete.
  46. input = input.substring(0, input.length - 1);
  47. cmdRepl.complete(input, function(err, res) {
  48. if (err) {
  49. sock.write('ERROR: ' + err + '\r\n');
  50. } else {
  51. sock.write(JSON.stringify(res) + '\r\n');
  52. }
  53. });
  54. } else {
  55. // Normal input
  56. input = input.trim();
  57. cmdRepl.stepEval(input, function(err, res) {
  58. if (err) {
  59. sock.write('ERROR: ' + err + '\r\n');
  60. return;
  61. }
  62. if (res === undefined) {
  63. res = '';
  64. }
  65. sock.write(res + '\r\n');
  66. });
  67. }
  68. });
  69. }).listen(port);
  70. console.log('Server listening on 127.0.0.1:' + port);
  71. };
  72. /**
  73. * Instantiate a repl to handle IO.
  74. * @private
  75. */
  76. WdRepl.prototype.initRepl_ = function() {
  77. var self = this;
  78. var cmdRepl = new CommandRepl(this.client);
  79. // Eval function for processing a single step in repl.
  80. var stepEval = function(cmd, context, filename, callback) {
  81. // The command that eval feeds is of the form '(CMD\n)', so we trim the
  82. // double quotes and new line.
  83. cmd = debuggerCommons.trimReplCmd(cmd);
  84. cmdRepl.stepEval(cmd, function(err, res) {
  85. // Result is a string representation of the evaluation.
  86. if (res !== undefined) {
  87. console.log(res);
  88. }
  89. callback(err, undefined);
  90. });
  91. };
  92. var replServer = repl.start({
  93. prompt: cmdRepl.prompt,
  94. input: process.stdin,
  95. output: process.stdout,
  96. eval: stepEval,
  97. useGlobal: false,
  98. ignoreUndefined: true,
  99. completer: cmdRepl.complete.bind(cmdRepl)
  100. });
  101. replServer.on('exit', function() {
  102. console.log('Element Explorer Exiting...');
  103. self.client.req({command: 'disconnect'}, function() {
  104. // TODO(juliemr): Investigate why this is necessary. At this point, there
  105. // should be no active listeners so this process should just exit
  106. // by itself.
  107. process.exit(0);
  108. });
  109. });
  110. };
  111. /**
  112. * Instantiate a repl or a server.
  113. * @private
  114. */
  115. WdRepl.prototype.initReplOrServer_ = function() {
  116. // Note instead of starting either repl or server, another approach is to
  117. // feed the server socket into the repl as the input/output streams. The
  118. // advantage is that the process becomes much more realistic because now we're
  119. // using the normal repl. However, it was not possible to test autocomplete
  120. // this way since we cannot immitate the TAB key over the wire.
  121. var debuggerServerPort = process.argv[4];
  122. if (debuggerServerPort) {
  123. this.initServer_(debuggerServerPort);
  124. } else {
  125. this.initRepl_();
  126. }
  127. };
  128. /**
  129. * Initiate the debugger.
  130. * @public
  131. */
  132. WdRepl.prototype.init = function() {
  133. var self = this;
  134. this.client = debuggerCommons.attachDebugger(process.argv[2], process.argv[3]);
  135. this.client.once('ready', function() {
  136. debuggerCommons.setEvaluateBreakpoint(self.client, function() {
  137. process.send('ready');
  138. self.client.reqContinue(function() {
  139. // Intentionally blank.
  140. });
  141. });
  142. self.initReplOrServer_();
  143. });
  144. };
  145. var wdRepl = new WdRepl();
  146. wdRepl.init();