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