Skip to content

Commit adc35ea

Browse files
committedMar 1, 2014
Keep track and initialize to nil used gvars
fixes #489
1 parent 8c56856 commit adc35ea

File tree

5 files changed

+44
-16
lines changed

5 files changed

+44
-16
lines changed
 

‎lib/opal/nodes/base.rb

+4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ def add_ivar(name)
123123
scope.add_scope_ivar name
124124
end
125125

126+
def add_gvar(name)
127+
scope.add_scope_gvar name
128+
end
129+
126130
def add_temp(temp)
127131
scope.add_scope_temp temp
128132
end

‎lib/opal/nodes/helpers.rb

+21-12
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,40 @@ module Nodes
33
module Helpers
44

55
# Reserved javascript keywords - we cannot create variables with the
6-
# same name
7-
RESERVED = %w[
8-
arguments break case catch char class const continue debugger default
9-
delete do else enum export extends false finally for function if import
10-
in instanceof let native new return static switch super this throw try
11-
true typeof var void while with undefined
12-
]
6+
# same name (ref: http://stackoverflow.com/a/9337272/601782)
7+
ES51_RESERVED_WORD = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/
8+
9+
# ES3 reserved words that aren’t ES5.1 reserved words
10+
ES3_RESERVED_WORD_EXCLUSIVE = /^(?:int|byte|char|goto|long|final|float|short|double|native|throws|boolean|abstract|volatile|transient|synchronized)$/
11+
12+
# Immutable properties of the global object
13+
IMMUTABLE_PROPS = /^(?:NaN|Infinity|undefined)$/
14+
15+
# Doesn't take in account utf8
16+
BASIC_IDENTIFIER_RULES = /^[$_a-z][$_a-z\d]*$/i
17+
1318

1419
def property(name)
15-
reserved?(name) ? "['#{name}']" : ".#{name}"
20+
valid_name?(name) ? ".#{name}" : "[#{name.inspect}]"
1621
end
1722

18-
def reserved?(name)
19-
RESERVED.include? name
23+
def valid_name?(name)
24+
BASIC_IDENTIFIER_RULES =~ name and not(
25+
ES51_RESERVED_WORD =~ name or
26+
ES3_RESERVED_WORD_EXCLUSIVE =~ name or
27+
IMMUTABLE_PROPS =~ name
28+
)
2029
end
2130

2231
def variable(name)
23-
reserved?(name.to_s) ? "#{name}$" : name
32+
valid_name?(name.to_s) ? name : "#{name}$"
2433
end
2534

2635
# Converts a ruby lvar/arg name to a js identifier. Not all ruby names
2736
# are valid in javascript. A $ suffix is added to non-valid names.
2837
# varibales
2938
def lvar_to_js(var)
30-
var = "#{var}$" if RESERVED.include? var.to_s
39+
var = "#{var}$" unless valid_name? var.to_s
3140
var.to_sym
3241
end
3342

‎lib/opal/nodes/scope.rb

+13-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class ScopeNode < Base
1515

1616
attr_reader :scope_name
1717
attr_reader :ivars
18+
attr_reader :gvars
1819

1920
attr_accessor :mid
2021

@@ -37,6 +38,7 @@ def initialize(*)
3738
@temps = []
3839
@args = []
3940
@ivars = []
41+
@gvars = []
4042
@parent = nil
4143
@queue = []
4244
@unique = 'a'
@@ -124,9 +126,14 @@ def to_vars
124126
"if (self#{ivar} == null) self#{ivar} = nil;\n"
125127
end
126128

129+
gv = gvars.map do |gvar|
130+
"if ($gvars#{gvar} == null) $gvars#{gvar} = nil;\n"
131+
end
132+
127133
indent = @compiler.parser_indent
128-
res = vars.empty? ? '' : "var #{vars.join ', '};"
129-
str = ivars.empty? ? res : "#{res}\n#{indent}#{iv.join indent}"
134+
str = vars.empty? ? '' : "var #{vars.join ', '};\n"
135+
str += "#{indent}#{iv.join indent}" unless ivars.empty?
136+
str += "#{indent}#{gv.join indent}" unless gvars.empty?
130137

131138
if class? and !@proto_ivars.empty?
132139
#raise "FIXME to_vars"
@@ -156,6 +163,10 @@ def add_scope_ivar(ivar)
156163
end
157164
end
158165

166+
def add_scope_gvar(gvar)
167+
@gvars << gvar unless @gvars.include? gvar
168+
end
169+
159170
def add_proto_ivar(ivar)
160171
@proto_ivars << ivar unless @proto_ivars.include? ivar
161172
end

‎lib/opal/nodes/variables.rb

+5-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ def var_name
8888

8989
def compile
9090
helper :gvars
91-
push "$gvars[#{var_name.inspect}]"
91+
name = property var_name
92+
add_gvar name
93+
push "$gvars#{name}"
9294
end
9395
end
9496

@@ -103,7 +105,8 @@ def var_name
103105

104106
def compile
105107
helper :gvars
106-
push "$gvars[#{var_name.inspect}] = "
108+
name = property var_name
109+
push "$gvars#{name} = "
107110
push expr(value)
108111
end
109112
end

‎spec/opal/filters/bugs/language.rb

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
fails "The defined? keyword for an expression with logical connectives returns nil for an expression with '!' and an unset global variable"
156156
fails "The defined? keyword for an expression with logical connectives returns nil for an expression with 'not' and an unset class variable"
157157
fails "The defined? keyword for an expression with logical connectives returns nil for an expression with '!' and an unset class variable"
158+
fails "The defined? keyword for variables returns nil for a global variable that has been read but not assigned to"
158159

159160
fails "An ensure block inside a begin block is executed even when a symbol is thrown in it's corresponding begin block"
160161
fails "An ensure block inside a method is executed even when a symbol is thrown in the method"

0 commit comments

Comments
 (0)
Please sign in to comment.