6

Well, there is not really much to explain. https://jsbin.com/raqajelufu/edit?html,js,output Illegal invocation exception is raised on any File object property access after being copied with angular.copy.

Is there any workaround, which would make watching for File object possible, considering $watch is using angular.copy internally according to https://docs.angularjs.org/api/ng/type/$rootScope.Scope?

Claies
  • 22,124
  • 4
  • 53
  • 77
Vasaka
  • 579
  • 6
  • 17
  • Have you tried with $watch or only calling copy explicitly as in your example? You can probably work around it by providing a destination to copy, as the problem seems to be when it tries to create one internally using Object.create(...), though I don't personally know how to workaround if you get the error with $watch when it calls copy itself.. – aw04 Jul 22 '15 at 18:12
  • I think your problem isn't with copying but with instantiation, see http://stackoverflow.com/questions/8390855/how-to-instantiate-a-file-object-in-javascript – yvesmancera Jul 22 '15 at 18:43
  • 1
    Calling `var f = new File([],"")` and then `f.name` does not yield an error, so I still think the problem is with copying – Vasaka Jul 22 '15 at 19:15
  • @aw04, yes $watch throws that error as well. Here is an example to show that https://jsbin.com/gatumewuwa/edit?html,js,output – Vasaka Jul 23 '15 at 07:10

1 Answers1

3

Which browser(s) are you seeing the issue on?

A similar question was asked a while ago which concluded that it could have to do with Chrome v43.

Some resources related to the issue:

Supposedly, Chrome v43 does not like the following in the angular.copy source:

var emptyObject = Object.create(Object.getPrototypeOf(source));

You could try any of the following to see if it suppresses your errors (regardless of your browser of choice):

  • Dont use angular.copy, by avoiding deep watches a la $scope.$watch('', fn, true)(jsbin) and go for something like _.cloneDeep(jsbin) from lodash when you need to make a deep copy of something.
  • Step back to Chrome v42 (if you are on v43).
  • Step back to Angular 1.2.28 where angular.copy does not call the above line. source (jsbin)

If you want to watch deeply but avoid angular.copy, I would do something like this (with the help of lodash.merge):

$scope.$watch(function () {
  return _.merge(src, dest);
}, callback);

yet another jsbin

That way you wouldn't call angular.copy and you would still have a 'deep watch' setup. Bare in mind, this is a very naive example and I have not tested it thoroughly but I think you could make it work very similarly to an angular deep watch with minimal effort.


Disclaimer: I haven't really dug that deep into what is actually going on the angular.copy source, the console and/or Chrome v43. It is somewhat of a gray area, but with the above suggestion(s) I have yet to trigger an Illegal Invocation.

Community
  • 1
  • 1