Skip to content

Conversation

@SamSaffron
Copy link
Collaborator

No description provided.

@SamSaffron
Copy link
Collaborator Author

@bnoordhuis I just tried latest on Discourse and it is failing due to this test:

  def test_function_cloning
    message = nil
    context = MiniRacer::Context.new
    context.attach("rails.logger.warn", proc { |msg| message = msg })
    context.eval <<~JS
               console = {
                 prefix: "[PrettyText] ",
                 log: function(...args){ rails.logger.info(console.prefix + args.join(" ")); },
               }
             JS

    context.eval("console.log('Hello', 'World!')")
    assert_equal "[PrettyText] Hello World!", message
  end

@bnoordhuis
Copy link
Collaborator

Typo? It says rails.logger.warn on one line and rails.logger.info on another.

@SamSaffron
Copy link
Collaborator Author

@bnoordhuis sorry about the typo fixed it, but test is still broken due to clone issue

Comment on lines +1082 to +1084
console = {
log: function(...args){ log(args.join(" ")); },
}
Copy link
Collaborator

@bnoordhuis bnoordhuis Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what the problem is: the result of this statement is (edit: an object containing) the log function object. The test passes when changed to this:

Suggested change
console = {
log: function(...args){ log(args.join(" ")); },
}
console = {
log: function(...args){ log(args.join(" ")); },
}
undefined

Let me think what a good solution is.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness sake, another workaround is to make the property non-enumerable:

Suggested change
console = {
log: function(...args){ log(args.join(" ")); },
}
console = {}
Object.defineProperty(console, "log", {value: function(...args){ log(args.join(" ")); }})

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we can just return something here , trouble of crashing on deserialozation boundary is that many eval and don’t care about result , even just saying “function” is fine

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For posterity, I think there are 4 options:

  1. do nothing and let the error bubble up (current situation)
  2. detect the error and return something else, like an empty object or a marker
  3. deep-copy the object and replace or drop function properties
  4. ditto but only shallow-copy the object, i.e., fix up only one level

3 is O(n) time and space, 4 is only a partial fix, so I guess 2 is the best option.

bnoordhuis added a commit to bnoordhuis/mini_racer that referenced this pull request Jan 9, 2025
Instead of trying to detect upfront if an object can be serialized,
just do it and see if it throws a DataCloneError.

Unexpected DataCloneErrors were of course already being handled but
the new approach does it in a centralized and generic manner.

Failed serialization now passes an object with a single "error" string
property back to Ruby land.

Fixes the failing test from rubyjs#329
SamSaffron pushed a commit that referenced this pull request Jan 9, 2025
Instead of trying to detect upfront if an object can be serialized,
just do it and see if it throws a DataCloneError.

Unexpected DataCloneErrors were of course already being handled but
the new approach does it in a centralized and generic manner.

Failed serialization now passes an object with a single "error" string
property back to Ruby land.

Fixes the failing test from #329
@SamSaffron SamSaffron closed this Jan 9, 2025
bnoordhuis added a commit to bnoordhuis/mini_racer that referenced this pull request Mar 13, 2025
Instead of trying to detect upfront if an object can be serialized,
just do it and see if it throws a DataCloneError.

Unexpected DataCloneErrors were of course already being handled but
the new approach does it in a centralized and generic manner.

Failed serialization now passes an object with a single "error" string
property back to Ruby land.

Fixes the failing test from rubyjs#329
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

Successfully merging this pull request may close these issues.

3 participants