Tenderlove Making

Pointcut Your Javascript

Sorry for all of the RKelly updates, but thats what I’ve been doing in my free time. I mean, besides J-School. But I don’t think anyone wants to read my poor Japanese!

I wanted to make my ASTs easily searchable, so I added an AOP style interface to my AST. The AST will now let you pointcut your javascript and give you back a list of all of the points it finds. Take this javascript for example: ~~~ javascript try { Element.update(‘another_id’,”blah blah blah”); Element.update(10,”blah blah blah”); } catch (e) { } ~~~ Lets say you wanted to find every place that Element.update() was called with 2 arguments, and mess with those arguments. You can pointcut the ast, then modify the arguments by giving the AST a pattern to match on like so: ~~~ ruby parser = RKelly::Parser.new ast = parser.parse(DATA.read) ast.pointcut(“Element.update(Object, Object)”).matches.each do |m| m.arguments.value.each { |x| x.value = rand(20) } end

puts ast.to_ecma ~~~ But lets say you only want to update the call that was made with a number as the first parameter. No problem! Just change your pattern to use a number, like so: ~~~ ruby parser = RKelly::Parser.new ast = parser.parse(DATA.read) ast.pointcut(“Element.update(Number, Object)”).matches.each do |m| m.arguments.value.each { |x| x.value = rand(20) } end

puts ast.to_ecma ~~~ You can even get more specific and match the arguments exactly. For example, matching just the function call where the first argument is ‘another_id’: ~~~ ruby parser = RKelly::Parser.new ast = parser.parse(DATA.read) ast.pointcut(“Element.update(‘another_id’, Object)”).matches.each do |m| m.arguments.value.each { |x| x.value = rand(20) } end ~~~ Maybe you don’t care the update is being called on an Element, but you want to match all places that update is being called on something. The pointcut will match on node type too, so this is a perfectly valid pattern: ~~~ ruby parser = RKelly::Parser.new ast = parser.parse(DATA.read) ast.pointcut(“ResolveNode.update(‘another_id’, Object)”).matches.each do |m| m.arguments.value.each { |x| x.value = rand(20) } end ~~~ Hopefully you get the picture. This feature isn’t full tested yet, but I think I might do my first RKelly release after I finish testing.

« go back