Skip to content

Instantly share code, notes, and snippets.

@Zapotek
Created December 4, 2011 17:01
Show Gist options
  • Select an option

  • Save Zapotek/1430686 to your computer and use it in GitHub Desktop.

Select an option

Save Zapotek/1430686 to your computer and use it in GitHub Desktop.
V8 interpreter with basic DOM in Ruby using TheRubyRacer and Taka
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
@laspluviosillas
Copy link
Copy Markdown

You just made my day sir.

@Zapotek
Copy link
Copy Markdown
Author

Zapotek commented Feb 3, 2012

Glad to hear it, you might want to check this out: https://github.com/Zapotek/dom-js-experiment

@laspluviosillas
Copy link
Copy Markdown

Just what I need. +1.

@laspluviosillas
Copy link
Copy Markdown

You should make this some sort of gem btw (I might contribute)

@Zapotek
Copy link
Copy Markdown
Author

Zapotek commented Feb 3, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment