Giter VIP home page Giter VIP logo

Comments (6)

sebnozzi avatar sebnozzi commented on June 8, 2024

Might be a regression of #2296

from opal.

hmdne avatar hmdne commented on June 8, 2024

I think this is a bug in Firefox, not Opal... why:

My test case:

puts "Hello"

def a
  1.times do
    raise RuntimeError, "Boom!"
  end
end

begin
  a
rescue Exception => e
  p `e.stack`
end

Then I run:

opal -Rgjs index.rb

(Note: gjs is a GNOME (Linux) JavaScript runtime that uses Firefox JS engine, if you don't have it use server).

Note that I specifically raise RuntimeError, because that's what's raised if no class is set.

A backtrace in e.stack is set for classes that are either of Exception class or a direct descendant of Exception. So, for those classes it is set:

  • StandardError
  • ScriptError
  • SystemExit

For those it's not set:

  • SyntaxError
  • RuntimeError

Perhaps we could work around that bug...

diff --git a/opal/corelib/error.rb b/opal/corelib/error.rb
index da74c1cea..9d6c24eb1 100644
--- a/opal/corelib/error.rb
+++ b/opal/corelib/error.rb
@@ -11,6 +11,10 @@ class ::Exception < `Error`
       error.name    = self.$$name;
       error.message = message;
       error.cause   = #{$!};
+
+      // A bug in Firefox would not set a stack for non-direct descendants of Error
+      error.stack   = (new Error).stack;
+
       Opal.send(error, error.$initialize, args);
 
       // Error.captureStackTrace() will use .name and .toString to build the

from opal.

hmdne avatar hmdne commented on June 8, 2024

Having tried to reproduce this in pure JavaScript, I think the issue goes deeper. My theory is that the stack is set in Error's constructor.

Consider this Opal code:

%x{
  class Test {
    constructor() {
      console.log("Hello world!");
    }
  }
}

class Test < `Test`; end
Test.new

class Test2 < Test; end
Test2.new

class Test3 < Test2; end
Test3.new

class Test4 < Test3; end
Test4.new

The first class is bridged to (NOT subclassing) JavaScript Test. The next ones are subclassing it. We would expect the JS constructor to be called on each one, yet only the first two call it.

Let's try this patch:

diff --git a/opal/corelib/runtime.js b/opal/corelib/runtime.js
index 11671ac13..9dfda69e1 100644
--- a/opal/corelib/runtime.js
+++ b/opal/corelib/runtime.js
@@ -567,7 +567,7 @@
   // @return new [Class]  or existing ruby class
   //
   function $allocate_class(name, superclass, singleton) {
-    var klass;
+    var klass, super_constructor;
 
     if (superclass != null && superclass.$$bridge) {
       // Inheritance from bridged classes requires
@@ -581,7 +581,9 @@
         return self;
       }
     } else {
-      klass = function(){};
+      klass = function() {
+        if (superclass) superclass.$$constructor(this, arguments);
+      };
     }
 
     if (name && name !== nil) {

Unfortunately, it doesn't fix the Firefox issue :(

from opal.

hmdne avatar hmdne commented on June 8, 2024

My theory was right (but code was wrong). I read more into $allocate_class and comments describes precisely what's happening. A correct patch is as follows:

diff --git a/opal/corelib/runtime.js b/opal/corelib/runtime.js
index 11671ac13..301139d42 100644
--- a/opal/corelib/runtime.js
+++ b/opal/corelib/runtime.js
@@ -538,6 +538,13 @@
   Opal.$$$ = Opal.const_get_qualified;
   Opal.$r = Opal.const_get_relative_factory;
 
+  function descends_from_bridged_class(klass) {
+    if (klass == null) return false;
+    if (klass.$$bridge) return klass;
+    if (klass.$$super) return descends_from_bridged_class(klass.$$super);
+    return false;
+  }
+
   // Modules & Classes
   // -----------------
 
@@ -567,14 +574,14 @@
   // @return new [Class]  or existing ruby class
   //
   function $allocate_class(name, superclass, singleton) {
-    var klass;
+    var klass, bridged_descendant;
 
-    if (superclass != null && superclass.$$bridge) {
+    if (bridged_descendant = descends_from_bridged_class(superclass)) {
       // Inheritance from bridged classes requires
       // calling original JS constructors
       klass = function() {
         var args = $slice(arguments),
-            self = new ($bind.apply(superclass.$$constructor, [null].concat(args)))();
+            self = new ($bind.apply(bridged_descendant.$$constructor, [null].concat(args)))();
 
         // and replacing a __proto__ manually
         $set_proto(self, klass.$$prototype);

from opal.

hmdne avatar hmdne commented on June 8, 2024

@elia I believe you could have encountered a similar issue while bridging the thing you were bridging...

from opal.

elia avatar elia commented on June 8, 2024

@hmdne yes! I ventured exactly in that area and this explains a couple of weird things I've seen

from opal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.