mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
added existence chains with '?.' -- soaks up attempts to access undefined properties, returning 'undefined'
This commit is contained in:
parent
9160500e84
commit
d728c3d669
5 changed files with 1225 additions and 1154 deletions
|
@ -4,7 +4,7 @@ class Parser
|
|||
token IF ELSE UNLESS
|
||||
token NUMBER STRING REGEX
|
||||
token TRUE FALSE YES NO ON OFF
|
||||
token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS
|
||||
token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS SOAK_ACCESS
|
||||
token CODE PARAM NEW RETURN
|
||||
token TRY CATCH FINALLY THROW
|
||||
token BREAK CONTINUE
|
||||
|
@ -242,7 +242,8 @@ rule
|
|||
# Accessing into an object or array, through dot or index notation.
|
||||
Accessor:
|
||||
PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) }
|
||||
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], true) }
|
||||
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :prototype) }
|
||||
| SOAK_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :soak) }
|
||||
| Index { result = val[0] }
|
||||
| Range { result = SliceNode.new(val[0]) }
|
||||
;
|
||||
|
|
|
@ -91,8 +91,15 @@ module CoffeeScript
|
|||
# 'if' will result in an [:IF, "if"] token.
|
||||
tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER
|
||||
tag = :LEADING_WHEN if tag == :WHEN && [:OUTDENT, :INDENT, "\n"].include?(last_tag)
|
||||
@tokens[-1][0] = :PROPERTY_ACCESS if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2] && @tokens[-2][1] == '.')
|
||||
@tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::'
|
||||
if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2] && @tokens[-2][1] == '.')
|
||||
if @tokens[-2][0] == "?"
|
||||
@tokens[-1][0] = :SOAK_ACCESS
|
||||
@tokens.delete_at(-2)
|
||||
else
|
||||
@tokens[-1][0] = :PROPERTY_ACCESS
|
||||
end
|
||||
end
|
||||
token(tag, identifier)
|
||||
@i += identifier.length
|
||||
end
|
||||
|
|
|
@ -333,7 +333,7 @@ module CoffeeScript
|
|||
attr_reader :last, :source
|
||||
|
||||
def initialize(base, properties=[])
|
||||
@base, @properties = base, properties
|
||||
@base, @properties = base, [properties].flatten
|
||||
end
|
||||
|
||||
def <<(other)
|
||||
|
@ -367,12 +367,23 @@ module CoffeeScript
|
|||
end
|
||||
|
||||
def compile_node(o)
|
||||
only = o.delete(:only_first)
|
||||
props = only ? @properties[0...-1] : @properties
|
||||
parts = [@base, props].flatten.map {|val| val.compile(o) }
|
||||
soaked = false
|
||||
only = o.delete(:only_first)
|
||||
props = only ? @properties[0...-1] : @properties
|
||||
baseline = @base.compile(o)
|
||||
parts = [baseline.dup]
|
||||
props.each do |prop|
|
||||
if prop.is_a?(AccessorNode) && prop.soak
|
||||
soaked = true
|
||||
parts[-1] << " == undefined ? undefined : #{baseline += prop.compile(o)}"
|
||||
else
|
||||
parts << prop.compile(o)
|
||||
end
|
||||
end
|
||||
@last = parts.last
|
||||
@source = parts.length > 1 ? parts[0...-1].join('') : nil
|
||||
write(parts.join(''))
|
||||
code = parts.join('')
|
||||
write(soaked ? "(#{code})" : code)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -380,9 +391,12 @@ module CoffeeScript
|
|||
# an accessor into the object's prototype.
|
||||
class AccessorNode < Node
|
||||
children :name
|
||||
attr_reader :soak
|
||||
|
||||
def initialize(name, prototype=false)
|
||||
@name, @prototype = name, prototype
|
||||
def initialize(name, tag=nil)
|
||||
@name = name
|
||||
@prototype = tag == :prototype
|
||||
@soak = tag == :soak
|
||||
end
|
||||
|
||||
def compile_node(o)
|
||||
|
|
File diff suppressed because it is too large
Load diff
13
test/fixtures/execution/test_existence.coffee
vendored
13
test/fixtures/execution/test_existence.coffee
vendored
|
@ -30,4 +30,15 @@ get_next_node: =>
|
|||
throw "up" if counter
|
||||
counter++
|
||||
|
||||
print(if get_next_node()? then true else false)
|
||||
print(if get_next_node()? then true else false)
|
||||
|
||||
|
||||
# Existence chains, soaking up undefined properties:
|
||||
|
||||
obj: {
|
||||
prop: "hello"
|
||||
}
|
||||
|
||||
print(obj?.prop is "hello")
|
||||
|
||||
print(obj?.prop?.non?.existent?.property is undefined)
|
Loading…
Add table
Add a link
Reference in a new issue