<shawn42>
my Stage class needs to have a method callable from "Ruby" but also needs to act like the wrapped object because it gets passed around internally in PIXI
<shawn42>
the prototype swapping feels wrong, but is that the way to go?
<adambeynon>
shawn42: I used that as a quick hack inside opal-jquery, just to get it working
<adambeynon>
we do need a way to support this though
<adambeynon>
so, you want the "ruby object" to be just the real js object?
<adambeynon>
like the way arrays in ruby are normal js arrays?
<shawn42>
yes, but it would be nice to be able to Ruby-ify the external interface... so that if any of my Ruby game code interacts with that object, I can use methods like add_child instead of addChild
<shawn42>
so if I could just have my cake and eat it too.. that'd be great =P
<adambeynon>
shawn42: sure. would you want to have all the Kernel/Object methods on there as well?
<adambeynon>
lol, yeh
<shawn42>
yeah, I think so. Given the $ prefix there shouldn't be any naming conflicts so that would work
<adambeynon>
shawn42: ok, well, at the moment, this requires the hacks you have setup, which is what we use in opal-jquery
<adambeynon>
but
<adambeynon>
Im thiking about a better way to do it
<adambeynon>
something like
<adambeynon>
class Stage < `window.PIXI.stage`; .... ; end
<adambeynon>
which will do all the work on setting up your native js prototype to work as a ruby object would
<adambeynon>
that doesnt currently work, but we used to have it, and it did work nicely
<shawn42>
yeah, that makes sense
<adambeynon>
the only thing to note is, that we wouldn't be able to support method_missing on that object
<shawn42>
I wonder if it makes more sense to treat it like a module that is being mixed in, rather than a base class
<shawn42>
class Stage; include `window.PIXI.stage`; ... ; end
<adambeynon>
we could do. the only thing to be careful of is that if you include any modules or define any methods before that, then we might loose them
<adambeynon>
basically, with this approach we rip out the current prototype and replace it with your native javascript prototype
<adambeynon>
thus loosing any methods already defined
<shawn42>
could we just loop over window.PIXI.stage's prototype and copy them into our prototype (leaving our previous functions in place)?
<shawn42>
<-- is not JS expert and doesn't remember exactly how JS prototypes work
<adambeynon>
shawn42: we can do it that way. but, if someone creates a new instance of `window.PIXI.stage` somewhere else, then it wont have any of our ruby methods
<adambeynon>
as we are basically creating a subclass of it (in this case)
<shawn42>
yeah, I didn't think of that
<adambeynon>
shawn42: recently I tried re-writing opal-jquery to use a wrapper class instead, and its too awkward
<adambeynon>
I had to keep converting back and forth between wrappers
<adambeynon>
it makes more sense to be to extend prototypes like this, when possible
<adambeynon>
the only big downside is loosing method_missing
<shawn42>
I wonder if you could just formally endorse your "hack"
<shawn42>
so I don't have to execute raw js / prototype trickery
<adambeynon>
shawn42: I will introduce something as we need it for jQuery
<adambeynon>
we have two options, as I see it
<adambeynon>
either:
<adambeynon>
(using jquery as an example)
<adambeynon>
class Element < `$`; ... ; end
<adambeynon>
or
<shawn42>
and just hide it behind some thing that says "if you extend a native class, you cannot extend Object"
<adambeynon>
Element = Class.new(`$`) do ... end
<adambeynon>
yep
<shawn42>
adambeynon: aren't those the same option ;)
<adambeynon>
shawn42: kind of :D they go through slightly different code, but yeah
<adambeynon>
we could support both, yes
<shawn42>
cool, +1
<adambeynon>
or, to be contraversial, if we introduced method_tables, then this would all be a lot easier
<adambeynon>
but, much uglier generated code
<adambeynon>
controversial*
<shawn42>
heh
<shawn42>
adambeynon: oh, one more thing
GitHub63 has joined #opal
GitHub63 has left #opal [#opal]
<GitHub63>
opal/master b68dc4e Adam Beynon: Fix lots of heredoc parsing bugs (needs cleanup)
<GitHub63>
[opal] adambeynon pushed 1 new commit to master: http://git.io/0m7Ecg
<meh`>
adambeynon, it might still be an extremely good idea to keep Native as is
<meh`>
adambeynon, especially in <IE9 adding things to objects might crash
<meh`>
if they're DOM and other kinds of "special" objects
<adambeynon>
meh`: how dangerous is it? Didn't prototype.js add all their methods to elements?
<meh`>
adambeynon, not in IE
<meh`>
you still had to wrap them
<meh`>
also I think passing anything but the real arguments to a function is going to make things very ugly
<meh`>
fucking up with arguments ends up breaking a lot of things
<meh`>
so I'd rather we stayed as we are
<meh`>
same goes with blocks
<meh`>
but I wouldn't oppose a debug-only $iter that does its thing internally
<meh`>
but yeah, don't underestimate the utility of arguments
<meh`>
we use it everywhere in the corelib
<adambeynon>
mainly for blocks. I would prefer to keep blocks as a normal argument setup (as in, dont pass self)
<meh`>
adambeynon, how do you mean?
<adambeynon>
well, only methods would accept `self` as their first value
<adambeynon>
blocks would still be `my_block(1, 2, 3)`
<meh`>
I don't know, I'm not convinced, we'll see how it goes
<adambeynon>
meh`: yeah, Im just playing with it. my main concern is that it will start generating really ugly code again, which is a massive blocker in itself
<adambeynon>
but, we now have a shed-load of tests, so we can really test performance of a larger code base
<adambeynon>
is that beign defined on the element itself?
<adambeynon>
being*
<meh`>
adambeynon, the $data? yes
<meh`>
it has to
<meh`>
there are other things being defined too
<meh`>
but now that I think of it calling them with the same method prefix was retarded of me
<meh`>
I'll change them when we have an official runtime special var prefix
<adambeynon>
meh`: was just wondering in terms of affecting native elements
<adambeynon>
ie7/8 etc
<meh`>
adambeynon, from the research I made those *should* work
<meh`>
even on IE6
<meh`>
but I can always fix it in the compatibility stuff
<adambeynon>
yeah, I think so
<meh`>
the issues mostly come when you touch the prototype
<adambeynon>
meh`: yeah, but *instances* seem to be ok
<adambeynon>
that was my thoughts with method_tables
<adambeynon>
.. if they work out
<meh`>
yeah
<meh`>
but I really don't like recv.$method(recv, ..)
<meh`>
:(
<adambeynon>
meh`: depends on what works out to be fastest
<adambeynon>
.call() seems to add extra overhead
<adambeynon>
or I assume it would
<meh`>
.call would be even worse
<meh`>
I don't like how it reads
<meh`>
I don't even want to imagine how "a".b.c.d would look
<adambeynon>
but, how about `StringSubclass.new("foo").b.c.d` ;)
<meh`>
but we can already achieve it with the prototype swizzling
<adambeynon>
yeh, but we have to forward everything through method_missing
<adambeynon>
dinner : back in 20
<meh`>
yes, but those are few cases
<meh`>
slowing down all cases and making the code uglier for some rare cases doesn't sound like a good idea
<meh`>
with the prototype swizzling you're only affected if you're using inherited classes
<meh`>
with the method tables everything is affected
<meh`>
from speed to readability
elia has quit [Quit: Computer has gone to sleep.]
<adambeynon>
but we cant prototype swizzle things like jquery for method_missing
<meh`>
why aren't you just wrapping it?
<meh`>
this is seamless integration all over again
<adambeynon>
jquery is very awkward to wrap
<meh`>
adambeynon, so is the DOM API
<adambeynon>
exactly
<meh`>
but they're limited cases
<meh`>
that's the point of a library
<meh`>
working around the awkwardness for everyone else to use
<meh`>
think about it well through
<adambeynon>
but thats fine for the dom, but everytime you want to work with another library, we keep having to have `element.to_n` calls all over the place
<meh`>
and that's the proper way to go, or we're going the seamless integration direction away
<meh`>
we're dealing an uglier generated code for some half-assed seamless integration
<meh`>
and slower too
<meh`>
so yeah, think it well through before merging it in, if you're going in that direction
<meh`>
I don't want to see another switcharoo game on master
<adambeynon>
yep. this will all be in a pull request back to master, with all the pros, cons + example code so it can be decided on then
<meh`>
adambeynon, you should also try using it in your applications
technoguyrob5 has joined #opal
<technoguyrob5>
I have a quick question
<technoguyrob5>
I'm trying to convert a ruby file I wrote to javascript
<technoguyrob5>
So I have to compile the operator code by hand ot JS
<technoguyrob5>
And then wrap it in %x ?
<meh`>
technoguyrob5, no
<meh`>
technoguyrob5, if it's a parsing error it's just a bug in the parser
<technoguyrob5>
Right
<technoguyrob5>
Removing all the operators in the first class
<technoguyrob5>
lines 87 through 141
<adambeynon>
ahhh, I found it
<technoguyrob5>
results in RuntimeError: parse error on value "end" (END) :(file):51
<adambeynon>
for ... in
<technoguyrob5>
Nice!
<technoguyrob5>
Is that the problem?
<adambeynon>
yeah, we havent sorted those yet
<technoguyrob5>
Just iterate manually
<technoguyrob5>
Ok great
<technoguyrob5>
And no ranges?
<meh`>
technoguyrob5, we support ranges
<meh`>
technoguyrob5, also I don't think you have to #to_a on the range to use for .. in
<adambeynon>
yeah, ranges are fine
<technoguyrob5>
(0..(@primes - 1).to_a.each it is
<meh`>
technoguyrob5, just to (1 .. (p - 1)).each { return x if (x * n % p) == 1 }
<technoguyrob5>
Thanks!
<meh`>
technoguyrob5, you don't need to call #to_a on an Enumerable
<meh`>
it's already Enumerable
<technoguyrob5>
Right
<technoguyrob5>
Good point
<meh`>
you're just slowing everything down that way :)
<adambeynon>
never used for-in loops, which is why they aren't done yet :P
<technoguyrob5>
Especially if it's large :)
<meh`>
yeah, neither did I
<adambeynon>
does a for-in just compile to #each ?
<technoguyrob5>
Hehe, yeah it was a bad habit
<meh`>
adambeynon, basically, yes
<meh`>
adambeynon, except it doesn't create a new scope
<meh`>
have fun figuring that out :P
<technoguyrob5>
oh man...
<adambeynon>
:(
<meh`>
adambeynon, if it were for me, I'd just declare it unsupported
<meh`>
we can't support the same semantics
<technoguyrob5>
So basically...
<technoguyrob5>
Since a new scope gets created
<technoguyrob5>
my .self's now won't work
<technoguyrob5>
So I need to make a local
<technoguyrob5>
_self = self
<meh`>
technoguyrob5, no, you don't have that problem
<technoguyrob5>
Want me to submit a pull request if I get the for in business sorted out?
<meh`>
for .. in works differently as to variable declarations, that's all
<meh`>
when you do a = 3 in a for .. in
<meh`>
it's available to the following code
<meh`>
in a block it's not the case
<adambeynon>
meh`: I think we could work around it. when the parser hits a new variable, we can get the iter to check if its marked as a for-in loop, and push the variable up a scope
<technoguyrob5>
ok you're right
<technoguyrob5>
1.9.3p392 :059 > class X 1.9.3p392 :060?> def set=(test) 1.9.3p392 :061?> print test 1.9.3p392 :062?> end 1.9.3p392 :063?> def test 1.9.3p392 :064?> (0..2).each { |x| self.set = x } 1.9.3p392 :065?> end 1.9.3p392 :066?> end => nil 1.9.3p392 :067 > X.new.test 012 => 0..2
<technoguyrob5>
The instance scope gets preserved
<meh`>
adambeynon, yeah, you can compile the body differently, and define temporaries in the outer scope
<meh`>
shouldn't be an issue
<meh`>
but I still think using for in Ruby is bad practice
<adambeynon>
eek, =begin..=end doesnt increase the line numbers correctly
<adambeynon>
need to fix that
<adambeynon>
meh`: I just compiled that file with master + method_table branch
<adambeynon>
I am now deleting thr mehod_table branch
<adambeynon>
;)
<technoguyrob5>
I'm not sure if I helped with Opal here or just confused you guys.. :P
<meh`>
adambeynon, hahaha
<adambeynon>
technoguyrob5: there is lots of confusion happening here, so its all good ;)
<adambeynon>
meh`: I have literally wasted a day
<meh`>
adambeynon, should have warned you
<meh`>
I just hope you don't come back to method_tables in few months when you forget about this :P
GitHub185 has joined #opal
GitHub185 has left #opal [#opal]
<GitHub185>
[opal] adambeynon deleted method_table at 88ec514: http://git.io/CNG51g
<adambeynon>
meh`: we have logs now - I can look back and remember the pains.
<adambeynon>
right, onto something useful now
<adambeynon>
Time + Date parsing, woohoo
<technoguyrob5>
Oh god, be careful...
<technoguyrob5>
JS dates are programmer hell
<technoguyrob5>
We had a bug in production in our customer dashboard because, well...apparently Date.parse("08/31/2013") = 08-30-2013
<technoguyrob5>
I can't remember if that's the right date, but it was something like that
<technoguyrob5>
Err, new Date() rather than .parse
<adambeynon>
technoguyrob5: yeah, Im not feeling overly optimistic about it
<adambeynon>
I might read through moment.js for some inspiration
<adambeynon>
although last time I looked, it was quite monolithic in size
<technoguyrob5>
I was relying on the fact that 3/4 = 0 in Ruby
<technoguyrob5>
And similar operations
<technoguyrob5>
But that fails in JS
<technoguyrob5>
so now I have to floor stuff
<adambeynon>
ah, yeh... floats and ints
<technoguyrob5>
How do I export things to global variables?
<technoguyrob5>
Like window.some_variable
<adambeynon>
$global.some_variable = 3.142
<adambeynon>
or
<technoguyrob5>
Awesome, thanks. Or Opal.
<technoguyrob5>
Opal.FiniteField e.g.
<technoguyrob5>
I will show you the fruits of my labor in a second
<adambeynon>
top level classes will be put onto Opal automatically
<adambeynon>
::FOO = 100 <- that will put any constant on Opal
<technoguyrob5>
Nice that works!
<technoguyrob5>
Last one, sorry to be such a bug: You guys haven't implemented any way to do IO streams on non-files, have you? I have one method that takes an IO object, usually a File, but I would like to be able to convert the resulting output to a string in JS so it can get appended to the DOM
<technoguyrob5>
e.g.
<technoguyrob5>
def some_method(stream)
<technoguyrob5>
stream << 'hello there'
<technoguyrob5>
stream
<technoguyrob5>
end
<technoguyrob5>
and then in JS I flush the stream
<meh`>
technoguyrob5, use StringIO
<technoguyrob5>
Awesome, it works, thank you
<fkchang>
adambeynon: any thoughts on method definitions/json? I realize that I pretty much have next week to put that into opal-inspector if you figure out a first pass
<adambeynon>
fkchang: I have been playing with it
<fkchang>
maybe a separate branch for a rubyconf version, leaving time for a real version later, seems like u have lots on ur plate
<adambeynon>
source_file + source_line would be useful too
<adambeynon>
and then opal-inspector can just go through it as it pleases
<fkchang>
that's not bad, though an array would make for costly lookups
<fkchang>
maybe a hash of fully qualified methods, as a start
<adambeynon>
yeah. the only thing I dont know, is how to get the browser to load these extra "metadata" files
<adambeynon>
i.e. how to automate it
<adambeynon>
sourcemaps are loaded by a simple comment in the generated source
<adambeynon>
but that wont really help in this case
<adambeynon>
unless Opal::Server offers some special path to load the information from
<fkchang>
compile option to preload everything?
<fkchang>
or maybe parse option in the new scheme
<adambeynon>
fkchang: do you imagine running opal-inspector using opal-sprockets (i.e. Opal::Server) ?
<adambeynon>
as in, would you compile everything using a Rake task, or would you run opal-inspector on the fly using the opal server?
<fkchang>
ideally I'd like to do both, my demo code is a static file, but I imagine real apps would be via some server, I'd target rails, sinatra and opal server
<meh`>
and lissio server :>
<fkchang>
is there a lissio server?
<fkchang>
running on elixir?
<meh`>
no, it's just a modified Opal::Server
<meh`>
to work with lissio
<meh`>
it will support prerendering of the frontend for crawling
<meh`>
it sends the index on everything that isn't a static file
<meh`>
to support HTML5 history
<adambeynon>
fkchang: If you run it through Opal::Server, it can be done VERY easily
<adambeynon>
static is a bit trickier
<fkchang>
adambeynon: so anyways, I don't know if there's an easy scheme to handle both static and dynamic querying. I suppose you could load up the hash, and if it's not there, and u know the system is server based, query the server
<fkchang>
adambeynon: I could do a version using the server
<adambeynon>
fkchang: with the timeframe, I think if we could do just Opal::Server for now, we can look again at static building
<adambeynon>
then it can just be an option on opal server
<adambeynon>
server.metadata = true
<adambeynon>
or whatever
<fkchang>
adambeynon: I'm good w/that. I think u had a "getting started w/opal server doc" somewhere
[spoiler] has quit [Ping timeout: 246 seconds]
<adambeynon>
fkchang: yeah, needs updating a bit, but it is there ;)
<fkchang>
adambeynon: that'd be cool. I need to put a blurb about opal-server into my preso too
<fkchang>
now if I can grok lissio in time, maybe I'll rewrite it w/lissio components
<adambeynon>
fkchang: and some tests written with rspec? ;)
<meh`>
fkchang, if you need anything just ask
<fkchang>
adambeynon: rspec would be cool, how's that coming along
<adambeynon>
fkchang: 1 parsing error and 2 line changes because they use mutable strings
<adambeynon>
apart from that, it runs like a champ
<meh`>
adambeynon, did you try sending a pull request for that?
<adambeynon>
meh`: not yet. Im still searching the code base for any other places that they use mutable strings
<adambeynon>
incase our code just hasnt caused it to run yet
<meh`>
it's basically the same kind of problem you're having now
<meh`>
but changing core methods is generally a very very bad idea
<technoguyrob5>
I knew there was a better way, but this was a half-Sunday project, so I couldn't be bothered to research the details. This is really nice to know
<technoguyrob5>
Maybe I'll start a Ruby implementation of Sage now that I know this... :p
<meh`>
technoguyrob5, and when you feel courageous you could move to using lissio instead of generating HTML and having a CSS file :P
<technoguyrob5>
meh`: Haha yeah, I know, I would do all this stuff, I've written compilers and managed massive Rails and Backbone projects, I was just super fast cranking out lazy ;) Funny is it probably would've taken less time that way