core-js: Polyfilled Float32Array constructor cannot be stringified

This

require('core-js'); 
console.log(typeof Float32Array, Float32Array);

results in error:

TypeError: Cannot convert undefined or null to object
    at toString (native)
    at Function.<anonymous> (...\node_modules\core-js\modules\_ctx.js:18:15)
    at exports.format (util.js:128:18)
    at Console.log (console.js:43:37)
    at repl:1:9
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:313:29)
    at bound (domain.js:280:14)

While the same code without core-js works as expected:

console.log(typeof Float32Array, Float32Array);

and outputs

function function Float32Array() { [native code] }

Another problem is that Float32Array behaviour was changed for no obvious reason and started to make problems. This was totally uncalled for and wasn’t easy to debug. Since current Node releases are considered virtually ES2015/ES2016-compliant, the one could reasonably assume that require('core-js') is the same thing as cherry-picking ES2017+ features - and this would be a mistake that may result in counter-intuitive issues like this one (#283 already addresses the problem with default polyfilling strategy).

core-js 2.4.1 node 7.2.0

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15 (10 by maintainers)

Most upvoted comments

Did some digging on this in my debugger - ultimately core-js gets to here:

return fn.apply(that, arguments);

Where:

  • that is Float32Array.prototype.toString
  • fn is Function.prototype.call
  • arguments.length is 0 (!)

Which is ultimately equivalent to doing:

Float32Array.prototype.toString.call();

Which ends in a TypeError. Unfortunately I wasn’t able to trace what lead to the function getting called with zero arguments in the first place. The callstack gave no clues; console.log() was the only thing above the offending call.

Found something else suspicious. The whole .toString() factory:

	module.exports = function(fn, that, length){
	  aFunction(fn);
	  if(that === undefined)return fn;
	  switch(length){
	    case 1: return function(a){
	      return fn.call(that, a);
	    };
	    case 2: return function(a, b){
	      return fn.call(that, a, b);
	    };
	    case 3: return function(a, b, c){
	      return fn.call(that, a, b, c);
	    };
	  }
	  return function(/* ...args */){
	    return fn.apply(that, arguments);
	  };
	};

length is undefined!