Walks a Javascript AST and finds the immediate members of the root scope, which is useful for “hoisting” var and function declaration to the top of the function.
Although the auto-hoisting is no longer used, this class is used to “discover” a function's variables and scope.
@return [Array<String>] the function names in the first level of this closure
@return [Hash] the scope maintained while walking the ast
@param opts [Hash] the options hash @option opts [Integer] :max_depth the maximum depth to hoist (1) @option opts [Scope] :parent_scope the owner's scope
# File lib/jsobfu/hoister.rb, line 20 def initialize(opts={}) @parent_scope = opts.fetch(:parent_scope, nil) @max_depth = 1 @depth = 0 @scope = {} @functions = [] super() end
@return [String] Javascript that declares the discovered variables
# File lib/jsobfu/hoister.rb, line 71 def scope_declaration(opts={}) keys = scope.keys.dup if opts.fetch(:shuffle, true) keys = keys.shuffle end keys.delete_if { |k| functions.include? k } if @parent_scope keys.delete_if { |k| @parent_scope.has_key? k } keys.map! { |k| @parent_scope.renames[k.to_s] || k } end if keys.empty? then '' else "var #{keys.join(",")};" end end
# File lib/jsobfu/hoister.rb, line 40 def visit_FunctionDeclNode(o) functions << o.value scope[o.value] = o end
# File lib/jsobfu/hoister.rb, line 29 def visit_SourceElementsNode(o) return if @max_depth and @depth >= @max_depth @depth += 1 o.value.each { |x| x.accept(self) } @depth -= 1 end
# File lib/jsobfu/hoister.rb, line 36 def visit_VarDeclNode(o) scope[o.name] = o end