Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$routeProvider.when() breaks instanceof operator  #15409

Open
@NicBright

Description

@NicBright

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
$routeProvider.when(path, route) now uses a shallow copy instead of angular.copy() which was used previously.

In the company I'm working we relied (until now) on the fact that we could use the instanceof operator on the route object. We use this for an important feature toggle to be able to "deactivate" certain parts of our application based on the route class.

Here's the code we use and which worked just fine prior to v1.5.7 where the shallowCopy-change was introduced (see below).

        $rootScope.$on('$routeChangeStart', function (event, nextRoute) {
            if ((nextRoute instanceof McsRoute))
            {
                if (McsSettingsService.isDeactivated()) {
                    $location.url('/tmp/mcs/comingsoon');
                }
            }
        });

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).
This code shows that angular.copy does not break instanceof operator:

var MyClass = function() { };
var myinstance = new MyClass();
angular.copy(myinstance) instanceof MyClass; // true

This code shows that shallowCopy DOES break instanceof operator (I slightly modified the version from shallowCopy.js to work in the console):

var MyClass = function() { };
var myinstance = new MyClass();

function shallowCopy(src, dst) {
  if (Array.isArray(src)) {
    dst = dst || [];

    for (var i = 0, ii = src.length; i < ii; i++) {
      dst[i] = src[i];
    }
  } else {
    dst = dst || {};

    for (var key in src) {
      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
        dst[key] = src[key];
      }
    }
  }

  return dst || src;
}

shallowCopy(myinstance) instanceof MyClass // false

What is the expected behavior?
The code snippet above (nextRoute instanceof McsRoute) should work.

Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.

The problem was introduced in v1.5.7 with 6d0dcca

Other information (e.g. stacktraces, related issues, suggestions how to fix)
#14478
#14699
#14750

As a fix I can think of two possible solutions:

  1. My favourite: I don't think that route objects need to be protected from being modified after they've been registered with the $routeProvider. No need to deep clone. No need to shallow copy. Just use the objects provided
  2. If the protection from being modified afterwards should stay, one could do the following:
    i) create a new object "newObject" and make sure it has the same [[Prototype]] as the route object
    ii) shallowCopy(route, newObject)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions