Skip to content

[interop] Argument handling inconsistent #314

Open
@fniephaus

Description

@fniephaus

When a function is called in JavaScript, there can be more arguments than needed. For example, Array.prototype.forEach() can be used like this:

$ polyglot --jvm --shell
GraalVM MultiLanguage Shell 20.1.0
Copyright (c) 2013-2019, Oracle and/or its affiliates
  JavaScript version 20.1.0
js> [1, 2, 3].forEach((currentValue) => console.log(currentValue))
1
2
3
js> [1, 2, 3].forEach((currentValue, index) => console.log(currentValue + "-" + index))
1-0
2-1
3-2
js> [1, 2, 3].forEach((currentValue, index, array) => console.log(currentValue + "-" + index + "-" + array))
1-0-1,2,3
2-1-1,2,3
3-2-1,2,3

However, when doing interop with other languages, the callback provided must consume exactly three arguments:

$ polyglot --jvm --shell
GraalVM MultiLanguage Shell 20.1.0
Copyright (c) 2013-2019, Oracle and/or its affiliates
  JavaScript version 20.1.0
  Python version 3.8.2
js> [1, 2, 3].forEach(Polyglot.eval("python", "lambda currentValue,index,array: print('%s-%s-%s' % (currentValue, index, array))"))
1-0-[1, 2, 3]
2-1-[1, 2, 3]
3-2-[1, 2, 3]
js> [1, 2, 3].forEach(Polyglot.eval("python", "lambda currentValue: print(currentValue)"))
TypeError: <lambda>() takes 1 positional argument but 3 were given

This is not expected from the user's point of view.

I believe the reason for this is that there's no way to determine the arity of an executable interop value prior invocation, so Graal.js always tries to execute the interop callback with three arguments. IIRC all callbacks are always invoked with three arguments. But in case of an anonymous JS function, unused arguments will just be ignored. A naive solution would be to retry invoking an interop executable with fewer arguments until success. If the invocation with no arguments fails, so must the interop call. That, however, may not be the best strategy to provide a more consistent user experience. Maybe the interop protocol needs some sort of arity mechanism, but that may need too support many kinds of arguments (positional, optional, keyword, splat, ...).

/cc @chumer and @LeonBein

Metadata

Metadata

Assignees

Labels

interopPolyglot Language Interoperability

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions