Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is_a? and kind_of? not working on an Array when two opal generated js are included (Chrome 33-39) #616

Closed
deployable opened this issue Oct 11, 2014 · 8 comments

Comments

@deployable
Copy link

I have an array that is having a bit of an identity crisis when the class lookup is done from within a callback and there is a second javascript generated from ruby with require 'opal' included in the page.

b = { one: 'one' }
a = [ 'status', 'request', 'headers', 'content' ]
c = Array.new()

Document.ready? do
  puts "is_a #{a.class}"
  puts "yep array" if a.is_a? Array

  puts "is_a #{b.class}"
  puts "yep hash" if b.is_a? Hash

  puts "is_a #{c.class}"
  puts "yep array" if c.is_a? Array
end

Results in:

is_a Array
is_a Hash
yep hash
is_a Array

It's been hard to create a simple test case to post reproducing the issue, very similar code in a separate script delivered out of the same Sinatra web app produces the correct results. I'm not intentionally messing with the Array class anywhere so I'm at a loss as to where it's coming from.

I can see what the issue is though, the class comparison is failing due to the passed in class Array which ends up being $opal.cm('Array') in the javascript does not include a _full_name property that the original object/self OpalClass includes.

Includes:

require 'opal'
require 'jquery'
require 'opal-jquery'
require 'json'

Versions:

Using sprockets 2.12.2
Using opal 0.6.2
Using opal-browser 0.2.0.beta1
Using opal-jquery 0.2.0
Using sinatra 1.4.5
@deployable
Copy link
Author

A simple test case.

Opal file: first.rb

require 'opal'
require 'jquery'
require 'opal-jquery'

array = [ 1, 2 ]
hash  = { one: 1, two: 2 }

puts 'normal'
puts 'ok is array' if array.is_a? Array
puts 'ok is hash' if hash.is_a? Hash

Document.ready? do

  puts 'event inside'
  puts 'ok is array' if array.is_a? Array
  puts 'ok is hash' if hash.is_a? Hash

end

Opal file: second.rb

require 'opal'

HTML file: test.html

<!doctype html>
<html>
  <head>
    <script src="/assets/first.js"></script>
    <script src="/assets/second.js"></script>
  </head>
  <body>
    <div id="content">here be asset_test content</div>
  </body>
</html>

@deployable
Copy link
Author

Out of interest, what is the normal way to have multiple independant Opal generated js files only include the single Opal runtime?

@deployable
Copy link
Author

State in the Opal.is_a function

console.log(search)
=> OpalClass {_id: 5, _alloc: function, _isClass: true, constructor: function, _super: OpalClass…}
Wrapper: OpalClass
  __inc__: Array[1]
  __parent: Object
  _alloc: function Array() { [native code] }
  _base_module: OpalClass
  _full_name: "Array"
  _id: 5
  _isClass: true_methods: Array[4]
  _name: "Array"
  _orig_scope: TopScope_proto: Array[0]
  _scope: TopScope
  _super: OpalClass
  constructor: function OpalClass() {}
  __proto__: mtor

console.log(klass)
=> OpalClass {_id: 5, _alloc: function, _isClass: true, constructor: function, _super: OpalClass…}
  Wrapper: OpalClass
  __inc__: Array[1]
  __parent: Object
  _alloc: function Array() { [native code] }
  _base_module: OpalClass
  _id: 5_isClass: true
  _methods: Array[0]
  _name: "Array"
  _orig_scope: TopScope
  _proto: Array[0]
  _scope: TopScope
  _super: OpalClassconstructor: function OpalClass() {}
  __proto__: mtor

klass === search
=> false

@elia
Copy link
Member

elia commented Oct 11, 2014

I'll add a check in the runtime to avoid loading it twice

@meh
Copy link
Member

meh commented Oct 11, 2014

Can you try on master please?

@deployable
Copy link
Author

@meh same on master, the above test produces:

normal
ok is array
ok is hash
event inside
ok is hash

@deployable
Copy link
Author

Extending the test a bit...

require 'opal'
require 'jquery'
require 'opal-jquery'

class B; end

def test
  puts 'Array'    if [].is_a? Array
  puts 'Hash'     if {}.is_a? Hash
  puts 'String'   if ''.is_a? String
  puts 'Fixnum'   if 5.is_a? Fixnum
  puts 'Numeric'  if 5.5.is_a? Numeric
  puts 'B'        if B.new.is_a? B
end

puts 'Outside:'
test

Document.ready? do
  puts 'Inside:'
  test
end

Gives me:

Outside:
Array
Hash
String
Fixnum
Numeric
B

Inside:
Hash
B

@elia elia closed this as completed in 176e118 Oct 11, 2014
@deployable
Copy link
Author

Thanks, that cleared up whatever was happening underneath

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants