From 4413fea8dc7d28ca63aba35b9cf83decf2246cc5 Mon Sep 17 00:00:00 2001 From: Lucas Mirelmann Date: Sun, 17 Jan 2016 21:29:21 +0100 Subject: [PATCH] fix($injector): Add support for native Safari classes Change the mechanism to detect if a function is a class so it is compatible with Safari 9. --- src/auto/injector.js | 30 +++++++++--------------------- test/ng/compileSpec.js | 3 ++- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/auto/injector.js b/src/auto/injector.js index 110627ed350a..11550f087d71 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -821,17 +821,6 @@ function createInjector(modulesToLoad, strictDi) { return args; } - function isClass(func) { - // IE 9-11 do not support classes and IE9 leaks with the code below. - if (msie <= 11) { - return false; - } - // Workaround for MS Edge. - // Check https://connect.microsoft.com/IE/Feedback/Details/2211653 - return typeof func === 'function' - && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func)); - } - function invoke(fn, self, locals, serviceName) { if (typeof locals === 'string') { serviceName = locals; @@ -843,15 +832,16 @@ function createInjector(modulesToLoad, strictDi) { fn = fn[fn.length - 1]; } - if (!isClass(fn)) { + try { // http://jsperf.com/angularjs-invoke-apply-vs-switch - // #5388 return fn.apply(self, args); - } else { - args.unshift(null); - /*jshint -W058 */ // Applying a constructor without immediate parentheses is the point here. - return new (Function.prototype.bind.apply(fn, args)); - /*jshint +W058 */ + } catch (e) { + // if `fn` is a class, then it needs to be called using `new` + if (e instanceof TypeError) { + return new (Function.prototype.bind.apply(fn, [null].concat(args)))(); + } else { + throw e; + } } } @@ -863,9 +853,7 @@ function createInjector(modulesToLoad, strictDi) { var args = injectionArgs(Type, locals, serviceName); // Empty object at position 0 is ignored for invocation with `new`, but required. args.unshift(null); - /*jshint -W058 */ // Applying a constructor without immediate parentheses is the point here. - return new (Function.prototype.bind.apply(ctor, args)); - /*jshint +W058 */ + return new (Function.prototype.bind.apply(ctor, args))(); } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index f885d3106433..3cd310fcd7be 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1,5 +1,6 @@ 'use strict'; +/* globals support: false */ describe('$compile', function() { function isUnknownElement(el) { @@ -4241,7 +4242,7 @@ describe('$compile', function() { it('should eventually expose isolate scope variables on ES6 class controller with controllerAs when bindToController is true', function() { - if (!/chrome/i.test(navigator.userAgent)) return; + if (!support.classes) return; /*jshint -W061 */ var controllerCalled = false; module(function($compileProvider) {