File: repl.coffee

package info (click to toggle)
coffeescript 2.7.0%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,360 kB
  • sloc: makefile: 20; xml: 9; sh: 6; javascript: 5
file content (140 lines) | stat: -rw-r--r-- 4,149 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
return if global.testingBrowser

os = require 'os'
fs = require 'fs'
path = require 'path'

# REPL
# ----
Stream = require 'stream'

class MockInputStream extends Stream
  constructor: ->
    super()
    @readable = true

  resume: ->

  emitLine: (val) ->
    @emit 'data', Buffer.from("#{val}\n")

class MockOutputStream extends Stream
  constructor: ->
    super()
    @writable = true
    @written = []

  write: (data) ->
    # console.log 'output write', arguments
    @written.push data

  lastWrite: (fromEnd = -1) ->
    @written[@written.length - 1 + fromEnd].replace /\r?\n$/, ''

# Create a dummy history file
historyFile = path.join os.tmpdir(), '.coffee_history_test'
fs.writeFileSync historyFile, '1 + 2\n'

testRepl = (desc, fn) ->
  input = new MockInputStream
  output = new MockOutputStream
  repl = Repl.start {input, output, historyFile}
  test desc, -> fn input, output, repl

ctrlV = { ctrl: true, name: 'v'}


testRepl 'reads history file', (input, output, repl) ->
  input.emitLine repl.history[0]
  eq '3', output.lastWrite()

testRepl "starts with coffee prompt", (input, output) ->
  eq 'coffee> ', output.lastWrite(0)

testRepl "writes eval to output", (input, output) ->
  input.emitLine '1+1'
  eq '2', output.lastWrite()

testRepl "comments are ignored", (input, output) ->
  input.emitLine '1 + 1 #foo'
  eq '2', output.lastWrite()

testRepl "output in inspect mode", (input, output) ->
  input.emitLine '"1 + 1\\n"'
  eq "'1 + 1\\n'", output.lastWrite()

testRepl "variables are saved", (input, output) ->
  input.emitLine "foo = 'foo'"
  input.emitLine 'foobar = "#{foo}bar"'
  eq "'foobar'", output.lastWrite()

testRepl "empty command evaluates to undefined", (input, output) ->
  # A regression fixed in Node 5.11.0 broke the handling of pressing enter in
  # the Node REPL; see https://github.com/nodejs/node/pull/6090 and
  # https://github.com/jashkenas/coffeescript/issues/4502.
  # Just skip this test for versions of Node < 6.
  return if parseInt(process.versions.node.split('.')[0], 10) < 6
  input.emitLine ''
  eq 'undefined', output.lastWrite()

testRepl "#4763: comment evaluates to undefined", (input, output) ->
  input.emitLine '# comment'
  eq 'undefined', output.lastWrite()

testRepl "#4763: multiple comments evaluate to undefined", (input, output) ->
  input.emitLine '### a ### ### b ### # c'
  eq 'undefined', output.lastWrite()

testRepl "ctrl-v toggles multiline prompt", (input, output) ->
  input.emit 'keypress', null, ctrlV
  eq '------> ', output.lastWrite(0)
  input.emit 'keypress', null, ctrlV
  eq 'coffee> ', output.lastWrite(0)

testRepl "multiline continuation changes prompt", (input, output) ->
  input.emit 'keypress', null, ctrlV
  input.emitLine ''
  eq '....... ', output.lastWrite(0)

testRepl "evaluates multiline", (input, output) ->
  # Stubs. Could assert on their use.
  output.cursorTo = (pos) ->
  output.clearLine = ->

  input.emit 'keypress', null, ctrlV
  input.emitLine 'do ->'
  input.emitLine '  1 + 1'
  input.emit 'keypress', null, ctrlV
  eq '2', output.lastWrite()

testRepl "variables in scope are preserved", (input, output) ->
  input.emitLine 'a = 1'
  input.emitLine 'do -> a = 2'
  input.emitLine 'a'
  eq '2', output.lastWrite()

testRepl "existential assignment of previously declared variable", (input, output) ->
  input.emitLine 'a = null'
  input.emitLine 'a ?= 42'
  eq '42', output.lastWrite()

testRepl "keeps running after runtime error", (input, output) ->
  input.emitLine 'a = b'
  input.emitLine 'a'
  eq 'undefined', output.lastWrite()

testRepl "#4604: wraps an async function", (input, output) ->
  return unless try new Function 'async () => {}' # Feature detect support for async functions.
  input.emitLine 'await new Promise (resolve) -> setTimeout (-> resolve 33), 10'
  setTimeout ->
    eq '33', output.lastWrite()
  , 20

testRepl "transpile REPL", (input, output) ->
  input.emitLine 'require("./test/importing/transpile_import").getSep()'
  eq "'#{path.sep.replace '\\', '\\\\'}'", output.lastWrite()

process.on 'exit', ->
  try
    fs.unlinkSync historyFile
  catch exception # Already deleted, nothing else to do.