-
-
Save stympy/3645591 to your computer and use it in GitHub Desktop.
V8 interpreter with basic DOM in Ruby using TheRubyRacer and Taka
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'v8' | |
require 'open-uri' | |
require 'pp' | |
require 'ap' | |
require 'taka' | |
require 'ostruct' | |
# | |
# Monkey patch all elements to include a 'style' attribute | |
# | |
class Nokogiri::XML::Element | |
attr_reader :style | |
class Style < OpenStruct | |
end | |
def initialize( *args ) | |
super | |
@style = Style.new | |
end | |
end | |
# | |
# Taka lacks a few important interfaces | |
# so I've added some rough ones for the test's sake | |
# | |
module Taka::DOM::Document | |
attr_accessor :location | |
end | |
class Window | |
attr_reader :document | |
attr_reader :navigator | |
attr_reader :readyState | |
attr_accessor :location | |
def initialize( html = '' ) | |
@document = Taka::DOM::HTML( html ) | |
@navigator = Navigator.new | |
@location = Location.new( '' ) | |
@document.location = Location.new( '' ) | |
ready! | |
end | |
def open( url ) | |
@document = Taka::DOM::HTML( Kernel::open( url ) ) | |
@document.location = @location = Location.new( url ) | |
ready! | |
self | |
end | |
def alert( msg ) | |
# puts msg | |
pp msg | |
ap '---------' | |
end | |
def debug( obj ) | |
ap obj | |
end | |
def window | |
self | |
end | |
private | |
def ready! | |
@readyState = 'complete' | |
end | |
end | |
class Window::Navigator | |
attr_accessor :userAgent | |
def initialize | |
@userAgent = 'Arachni' | |
end | |
end | |
class Window::Location | |
def initialize( url ) | |
@url = URI( url ) | |
end | |
def host | |
@url.host + ':' + @url.port.to_s | |
end | |
def hostname | |
@url.host | |
end | |
def href | |
@url.to_s | |
end | |
def path | |
@url.path | |
end | |
def port | |
@url.port | |
end | |
# def hash | |
# return 0 if !@url.fragment | |
# '#' + @url.fragment | |
# end | |
def search | |
'?' + @url.query | |
end | |
def protocol | |
@url.scheme + ':' | |
end | |
def to_s | |
@url.to_s | |
end | |
end | |
# | |
# Taken from a Johnson example | |
# | |
html = <<EOHTML | |
<html> | |
<head> | |
<script> | |
function populateDropDown() { | |
var select = document.getElementById('colors'); | |
var options = ['red', 'green', 'blue', 'black']; | |
var i; | |
for( i = 0; i < options.length; i++ ) { | |
var option = document.createElement( 'option' ); | |
option.appendChild( document.createTextNode( options[i] ) ); | |
option.value = options[i]; | |
select.appendChild( option ); | |
} | |
} | |
div = document.createElement( "div" ); | |
div.style.display="none"; | |
div.textContent = 'Test div'; | |
body = document.getElementsByTagName('body')[0]; | |
body.appendChild( div ); | |
</script> | |
</head> | |
<body onload="populateDropDown()"> | |
<h1>Behold the V8</h1> | |
<form> | |
<select id="colors"> | |
</select> | |
</form> | |
</body> | |
</html> | |
EOHTML | |
window = Window.new( html ) | |
document = window.document | |
V8::Context.new( :with => window ) do |cxt| | |
document.xpath( './/script' ).each { | |
|script| | |
if src = script['src'] | |
src = script['src'].to_s | |
code = IO.read( open( src ) ) | |
else | |
code = script.text | |
src = 'EMBEDED' | |
end | |
begin | |
cxt.eval( code ) | |
rescue Exception => e | |
ap src | |
code.split( "\n" ).each_with_index { | |
|line, i| | |
puts "#{i+1} #{line}" | |
} | |
raise e | |
end | |
} | |
# should be 0 | |
p document.getElementsByTagName('option').length | |
# execute body's onload which will create the options | |
p cxt.eval document.getElementsByTagName('body')[0].onload | |
# should be 4 | |
p document.getElementsByTagName('option').length | |
# HTML code with updated DOM | |
# puts window.document.to_html | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment