Esben Andreasen
esben at esbena.dk
Mon Oct 17 07:11:39 UTC 2016
Thanks. That makes sense.
Two follow-ups, if I may:
A.
Where can I read about such non-ECMA-standard features in Nashorn?
B.
ECMAScript 6 includes `String.prototype.startsWith`, but it is not
supported by Nashorn in ES6-mode:
```
1 $ jjs -version --language=es6
2 nashorn 1.8.0_101
3 jjs> typeof String.prototype.startsWith
4 undefined
```
And it is unclear whether Nashorn intends to support it yet
(https://bugs.openjdk.java.net/browse/JDK-8066046).
So, is it a deliberate omission?
---
Esben
On Mon, Oct 17, 2016 at 7:44 AM Attila Szegedi <szegedia at gmail.com> wrote:
> it’s a side effect of the fact that primitive strings values in Nashorn
> are instances of java.lang.String, and the fact that with Nashorn you can
> invoke methods on Java objects, therefore “startsWith” is a Java String
> method.
>
> While Java methods also don’t inherit from Function.prototype (hence, you
> can’t call “call” on them as you have correctly observed), implementations
> of Function.prototype.call and .apply are actually coded so that they do
> work on them with a not terribly obvious, but correct invocation:
>
> var sw = "".startsWith
> Function.prototype.call.call(sw, "abc", "a")
>
> should return true. Note that since the expression fn.call.call is totally
> unbound from the fn that produced it, you can use any “fn”; I usually use
> “Function” for some semblance of clarity:
>
> Function.call.call(sw, "abc", "a")
>
> Finally, .startsWith is only present on primitive String values (as
> they’re java.lang.String), not on JS String objects, that’s why you were
> getting results you didn’t expect from “typeof Object(string).startsWith”
>
> HTH,
> Attila.
>
>
> > On 16 Oct 2016, at 13:42, Esben Andreasen <esben at esbena.dk> wrote:
> >
> > Hi
> >
> > I am not sure if this is a bug or feature of the Nashorn engine. But
> > it looks like some String-prototype methods are missing, yet the
> > methods are somehow present when used in the right way.
> >
> > Minimal example: calling `startsWith` by using `call`:
> >
> > ```
> > 1 $ jjs -v
> > 2 jjs> String.prototype.startsWith.call('abc', 'ab')
> > 3 <shell>:1 TypeError: Cannot read property "call" from undefined
> > ```
> >
> > Expected behavior:
> >
> > Not a type error, for multiple reasons:
> >
> > 1. Other JavaScript engines do not throw a type error.
> > 2. The equivalent code `"abc".startsWith("ab")` does not throw a type
> error.
> >
> >
> > Further investigation:
> >
> > ```
> > 1 $ jjs -v
> > 2 nashorn 1.8.0_101
> > 3 jjs> "abc".startsWith('ab')
> > 4 true
> > 5 jjs> "abc".startsWith
> > 6 [jdk.internal.dynalink.beans.OverloadedDynamicMethod
> > boolean java.lang.String.startsWith(String,int)
> > boolean java.lang.String.startsWith(String)
> > ]
> > 7 jjs> "abc".startsWith.call("abc", "ab")
> > 8 <shell>:1 TypeError: "abc".startsWith.call is not a function
> > 9 jjs> typeof String.prototype.startsWith
> > 10 undefined
> > 11 jjs> String.prototype.split.call("abc", "b")
> > 12 a,c
> > ```
> >
> > Interpretation:
> >
> > It looks like `startsWith` is not present on the String-prototype, yet
> > it is present on the String-primitives. Other String-prototype methods
> > (`split`) are however present.
> >
> > Further notes:
> >
> > This also applies to `String.prototype.endsWith`.
> >
> >
> > Related bug/feature: primitive values are not wrapped properly:
> >
> > ```
> > 1 $ jjs -v
> > 2 jjs> typeof Object("abc").startsWith
> > 3 undefined
> > ```
> >
> > -
> >
> > Esben
>
>
More information about the nashorn-dev
mailing list