paulmillr / es6-shim

ECMAScript 6 compatibility shims for legacy JS engines
http://paulmillr.com
MIT License
3.11k stars 387 forks source link

Safari <=9, different behaviour with `(new Function()).name` #390

Closed Xotic750 closed 8 years ago

Xotic750 commented 8 years ago

In Safari 9 I notice that it behaves differently to all other environments I have tested so far.

var f = new Function();
alert(f.name);

https://jsfiddle.net/Xotic750/mqabqdm0/ On Safari this alerts 'anonymous', but everywhere else I have tested it alerts '' https://saucelabs.com/beta/tests/e755ffaa8c744824b288d2ec6b6b0366/watch

cscott commented 8 years ago

That's a Safari bug, then, and not much es6-shim can do about it.

node/v8 has a similar version of the bug -- the ES6 says that f.hasOwnProperty('name') should return false if f is an anonymous function. But in the latest node, f.name is an own property, with the value ''. (Function.prototype.name = '' so the value is right, it just should be inherited from the prototype, not be an own property.)

Anyway, I don't think there's anything we can do about it -- everyone seems to correctly implement f.name as not writable, so we can't fix it.

Xotic750 commented 8 years ago

Thanks. There seem to be quite a few non-fixable bugs within ES6. At least it is documented. ;)

cscott commented 8 years ago

Said differently -- "JavaScript engines have a ways to go before they faithfully implement all of ES6."

Xotic750 commented 8 years ago

I don't know if there is a bug report with Safari for this, actually not even sure where to look.

Xotic750 commented 8 years ago

I tried submitting a bug via their Bug Reporter, but my pointer just spins and spins and spins. :/

ljharb commented 8 years ago

I'm going to close this since function name stuff is unshimmable.

JakeChampion commented 8 years ago

I was looking into how we could polyfill Function.prototype.name and have come across a partial implementation --

var fnNamePrefixRegex = /^[\S\s]*?function\s*/;
var fnNameSuffixRegex = /[\s\(\/][\S\s]+$/;

Object.defineProperty(Function.prototype, "name", {
    get: name
});

function name() {
  var name = "";
  if (this === Function || this === Function.prototype.constructor) {
    name = "Function";
  }
  else if (this !== Function.prototype) {
    name = ("" + this).replace(fnNamePrefixRegex, "").replace(fnNameSuffixRegex, "");
  }
  return name;
}

@ljharb By unshimmable do you mean it is not feasible or do you mean impossible?

ljharb commented 8 years ago

@JakeChampion impossible. The property is nonconfigurable in everything but IE (prior to ES6, which makes it configurable). However, in IE 9 - 11, you could probably add that getter, but I suspect there would be many edge cases, including "native code" functions.