mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Merge branch 'master' of github.com:jashkenas/coffeescript into 1.12.4
# Conflicts: # Cakefile
This commit is contained in:
commit
ee8f022317
14 changed files with 144 additions and 28 deletions
5
Cakefile
5
Cakefile
|
@ -100,10 +100,7 @@ watchAndBuildAndTest = (harmony = no) ->
|
|||
if eventType is 'change'
|
||||
log "src/#{filename} changed, rebuilding..."
|
||||
buildAndTest (filename is 'grammar.coffee'), harmony
|
||||
fs.watch 'test/',
|
||||
interval: 200
|
||||
recursive: yes
|
||||
, (eventType, filename) ->
|
||||
fs.watch 'test/', {interval: 200, recursive: yes}, (eventType, filename) ->
|
||||
if eventType is 'change'
|
||||
log "test/#{filename} changed, rebuilding..."
|
||||
buildAndTest no, harmony
|
||||
|
|
|
@ -385,7 +385,8 @@
|
|||
} else if (sources[filename] != null) {
|
||||
answer = compile(sources[filename], {
|
||||
filename: filename,
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
literate: helpers.isLiterate(filename)
|
||||
});
|
||||
return answer.sourceMap;
|
||||
} else {
|
||||
|
|
|
@ -409,11 +409,11 @@
|
|||
double: true
|
||||
}, this.formatHeregex);
|
||||
if (flags) {
|
||||
this.token(',', ',', index, 0);
|
||||
this.token('STRING', '"' + flags + '"', index, flags.length);
|
||||
this.token(',', ',', index - 1, 0);
|
||||
this.token('STRING', '"' + flags + '"', index - 1, flags.length);
|
||||
}
|
||||
this.token(')', ')', end, 0);
|
||||
this.token('REGEX_END', ')', end, 0);
|
||||
this.token(')', ')', end - 1, 0);
|
||||
this.token('REGEX_END', ')', end - 1, 0);
|
||||
}
|
||||
return end;
|
||||
};
|
||||
|
|
|
@ -1024,6 +1024,22 @@
|
|||
|
||||
Call.prototype.children = ['variable', 'args'];
|
||||
|
||||
Call.prototype.updateLocationDataIfMissing = function(locationData) {
|
||||
var base, ref3;
|
||||
if (this.locationData && this.needsUpdatedStartLocation) {
|
||||
this.locationData.first_line = locationData.first_line;
|
||||
this.locationData.first_column = locationData.first_column;
|
||||
base = ((ref3 = this.variable) != null ? ref3.base : void 0) || this.variable;
|
||||
if (base.needsUpdatedStartLocation) {
|
||||
this.variable.locationData.first_line = locationData.first_line;
|
||||
this.variable.locationData.first_column = locationData.first_column;
|
||||
base.updateLocationDataIfMissing(locationData);
|
||||
}
|
||||
delete this.needsUpdatedStartLocation;
|
||||
}
|
||||
return Call.__super__.updateLocationDataIfMissing.apply(this, arguments);
|
||||
};
|
||||
|
||||
Call.prototype.newInstance = function() {
|
||||
var base, ref3;
|
||||
base = ((ref3 = this.variable) != null ? ref3.base : void 0) || this.variable;
|
||||
|
@ -1032,6 +1048,7 @@
|
|||
} else {
|
||||
this.isNew = true;
|
||||
}
|
||||
this.needsUpdatedStartLocation = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -2059,7 +2076,7 @@
|
|||
|
||||
ModuleSpecifier.prototype.compileNode = function(o) {
|
||||
var code;
|
||||
o.scope.add(this.identifier, this.moduleDeclarationType);
|
||||
o.scope.find(this.identifier, this.moduleDeclarationType);
|
||||
code = [];
|
||||
code.push(this.makeCode(this.original.value));
|
||||
if (this.alias != null) {
|
||||
|
|
|
@ -45,11 +45,14 @@
|
|||
return this.parent.namedMethod();
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name) {
|
||||
Scope.prototype.find = function(name, type) {
|
||||
if (type == null) {
|
||||
type = 'var';
|
||||
}
|
||||
if (this.check(name)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, 'var');
|
||||
this.add(name, type);
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
@ -366,6 +366,7 @@ getSourceMap = (filename) ->
|
|||
answer = compile sources[filename],
|
||||
filename: filename
|
||||
sourceMap: yes
|
||||
literate: helpers.isLiterate filename
|
||||
answer.sourceMap
|
||||
else
|
||||
null
|
||||
|
|
|
@ -343,10 +343,10 @@ exports.Lexer = class Lexer
|
|||
@token 'CALL_START', '(', 0, 0
|
||||
@mergeInterpolationTokens tokens, {delimiter: '"', double: yes}, @formatHeregex
|
||||
if flags
|
||||
@token ',', ',', index, 0
|
||||
@token 'STRING', '"' + flags + '"', index, flags.length
|
||||
@token ')', ')', end, 0
|
||||
@token 'REGEX_END', ')', end, 0
|
||||
@token ',', ',', index - 1, 0
|
||||
@token 'STRING', '"' + flags + '"', index - 1, flags.length
|
||||
@token ')', ')', end - 1, 0
|
||||
@token 'REGEX_END', ')', end - 1, 0
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -633,6 +633,21 @@ exports.Call = class Call extends Base
|
|||
|
||||
children: ['variable', 'args']
|
||||
|
||||
# When setting the location, we sometimes need to update the start location to
|
||||
# account for a newly-discovered `new` operator to the left of us. This
|
||||
# expands the range on the left, but not the right.
|
||||
updateLocationDataIfMissing: (locationData) ->
|
||||
if @locationData and @needsUpdatedStartLocation
|
||||
@locationData.first_line = locationData.first_line
|
||||
@locationData.first_column = locationData.first_column
|
||||
base = @variable?.base or @variable
|
||||
if base.needsUpdatedStartLocation
|
||||
@variable.locationData.first_line = locationData.first_line
|
||||
@variable.locationData.first_column = locationData.first_column
|
||||
base.updateLocationDataIfMissing locationData
|
||||
delete @needsUpdatedStartLocation
|
||||
super
|
||||
|
||||
# Tag this invocation as creating a new instance.
|
||||
newInstance: ->
|
||||
base = @variable?.base or @variable
|
||||
|
@ -640,6 +655,7 @@ exports.Call = class Call extends Base
|
|||
base.newInstance()
|
||||
else
|
||||
@isNew = true
|
||||
@needsUpdatedStartLocation = true
|
||||
this
|
||||
|
||||
# Soaked chained invocations unfold into if/else ternary structures.
|
||||
|
@ -1352,7 +1368,7 @@ exports.ModuleSpecifier = class ModuleSpecifier extends Base
|
|||
children: ['original', 'alias']
|
||||
|
||||
compileNode: (o) ->
|
||||
o.scope.add @identifier, @moduleDeclarationType
|
||||
o.scope.find @identifier, @moduleDeclarationType
|
||||
code = []
|
||||
code.push @makeCode @original.value
|
||||
code.push @makeCode " as #{@alias.value}" if @alias?
|
||||
|
|
|
@ -44,9 +44,9 @@ function object that has a name filled in, or bottoms out.
|
|||
Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.
|
||||
|
||||
find: (name) ->
|
||||
find: (name, type = 'var') ->
|
||||
return yes if @check name
|
||||
@add name, 'var'
|
||||
@add name, type
|
||||
no
|
||||
|
||||
Reserve a variable name as originating from a function parameter for this
|
||||
|
@ -116,4 +116,3 @@ of this scope.
|
|||
|
||||
assignedVariables: ->
|
||||
"#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned
|
||||
|
||||
|
|
|
@ -71,20 +71,21 @@ if require?
|
|||
|
||||
test "#2849: compilation error in a require()d file", ->
|
||||
# Create a temporary file to require().
|
||||
ok not fs.existsSync 'test/syntax-error.coffee'
|
||||
fs.writeFileSync 'test/syntax-error.coffee', 'foo in bar or in baz'
|
||||
tempFile = path.join os.tmpdir(), 'syntax-error.coffee'
|
||||
ok not fs.existsSync tempFile
|
||||
fs.writeFileSync tempFile, 'foo in bar or in baz'
|
||||
|
||||
try
|
||||
assertErrorFormat '''
|
||||
require './test/syntax-error'
|
||||
''',
|
||||
assertErrorFormat """
|
||||
require '#{tempFile}'
|
||||
""",
|
||||
"""
|
||||
#{path.join __dirname, 'syntax-error.coffee'}:1:15: error: unexpected in
|
||||
#{fs.realpathSync tempFile}:1:15: error: unexpected in
|
||||
foo in bar or in baz
|
||||
^^
|
||||
"""
|
||||
finally
|
||||
fs.unlinkSync 'test/syntax-error.coffee'
|
||||
fs.unlinkSync tempFile
|
||||
|
||||
test "#3890 Error.prepareStackTrace doesn't throw an error if a compiled file is deleted", ->
|
||||
# Adapted from https://github.com/atom/coffee-cash/blob/master/spec/coffee-cash-spec.coffee
|
||||
|
|
|
@ -585,6 +585,29 @@ test "Verify indented heredocs have the right position", ->
|
|||
eq stringToken[2].last_line, 3
|
||||
eq stringToken[2].last_column, 4
|
||||
|
||||
test "Verify heregexes with interpolations have the right ending position", ->
|
||||
source = '''
|
||||
[a ///#{b}///g]
|
||||
'''
|
||||
[..., stringEnd, comma, flagsString, regexCallEnd, regexEnd, fnCallEnd,
|
||||
arrayEnd, terminator] = CoffeeScript.tokens source
|
||||
|
||||
eq comma[0], ','
|
||||
eq arrayEnd[0], ']'
|
||||
|
||||
assertColumn = (token, column) ->
|
||||
eq token[2].first_line, 0
|
||||
eq token[2].first_column, column
|
||||
eq token[2].last_line, 0
|
||||
eq token[2].last_column, column
|
||||
|
||||
arrayEndColumn = arrayEnd[2].first_column
|
||||
for token in [comma, flagsString]
|
||||
assertColumn token, arrayEndColumn - 2
|
||||
for token in [regexCallEnd, regexEnd, fnCallEnd]
|
||||
assertColumn token, arrayEndColumn - 1
|
||||
assertColumn arrayEnd, arrayEndColumn
|
||||
|
||||
test "Verify all tokens get a location", ->
|
||||
doesNotThrow ->
|
||||
tokens = CoffeeScript.tokens testScript
|
||||
|
|
|
@ -733,3 +733,19 @@ test "export an imported aliased member named default", ->
|
|||
default as def
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#4394: export shouldn't prevent variable declarations", ->
|
||||
input = """
|
||||
x = 1
|
||||
export { x }
|
||||
"""
|
||||
output = """
|
||||
var x;
|
||||
|
||||
x = 1;
|
||||
|
||||
export {
|
||||
x
|
||||
};
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
|
|
@ -38,3 +38,43 @@ test "operator precedence for binary ? operator", ->
|
|||
eq expression.second.first.base.value, 'b'
|
||||
eq expression.second.operator, '&&'
|
||||
eq expression.second.second.base.value, 'c'
|
||||
|
||||
test "new calls have a range including the new", ->
|
||||
source = '''
|
||||
a = new B().c(d)
|
||||
'''
|
||||
block = CoffeeScript.nodes source
|
||||
|
||||
assertColumnRange = (node, firstColumn, lastColumn) ->
|
||||
eq node.locationData.first_line, 0
|
||||
eq node.locationData.first_column, firstColumn
|
||||
eq node.locationData.last_line, 0
|
||||
eq node.locationData.last_column, lastColumn
|
||||
|
||||
[assign] = block.expressions
|
||||
outerCall = assign.value
|
||||
innerValue = outerCall.variable
|
||||
innerCall = innerValue.base
|
||||
|
||||
assertColumnRange assign, 0, 15
|
||||
assertColumnRange outerCall, 4, 15
|
||||
assertColumnRange innerValue, 4, 12
|
||||
assertColumnRange innerCall, 4, 10
|
||||
|
||||
test "location data is properly set for nested `new`", ->
|
||||
source = '''
|
||||
new new A()()
|
||||
'''
|
||||
block = CoffeeScript.nodes source
|
||||
|
||||
assertColumnRange = (node, firstColumn, lastColumn) ->
|
||||
eq node.locationData.first_line, 0
|
||||
eq node.locationData.first_column, firstColumn
|
||||
eq node.locationData.last_line, 0
|
||||
eq node.locationData.last_column, lastColumn
|
||||
|
||||
[outerCall] = block.expressions
|
||||
innerCall = outerCall.variable
|
||||
|
||||
assertColumnRange outerCall, 0, 12
|
||||
assertColumnRange innerCall, 4, 10
|
||||
|
|
|
@ -109,4 +109,6 @@ testRepl "keeps running after runtime error", (input, output) ->
|
|||
eq 'undefined', output.lastWrite()
|
||||
|
||||
process.on 'exit', ->
|
||||
fs.unlinkSync historyFile
|
||||
try
|
||||
fs.unlinkSync historyFile
|
||||
catch exception # Already deleted, nothing else to do.
|
||||
|
|
Loading…
Reference in a new issue