Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emit() arguments #54

Closed
jkirkwood opened this issue Apr 15, 2014 · 4 comments
Closed

emit() arguments #54

jkirkwood opened this issue Apr 15, 2014 · 4 comments
Labels

Comments

@jkirkwood
Copy link
Contributor

I've been experiencing some strange problems when using the emit function with multiple data arguments.

For instance when I call

socket.emit('machines:getHwStatusUpdates', machineId, device, null,
  function(err, u) {...});

At the beginning of the emit function the arguments array looks as expected:

0: "machines:getHwStatusUpdates"
1: 16
2: "modem"
3: null
4: function (err, u) {

However, after var callback = arguments[lastIndex] is executed the arguments array is altered like this:

0: "machines:getHwStatusUpdates"
1: 16
2: function (err, u) {
3: null
4: function (err, u) {

It appears that callback defined in the function params still points to the arguments array during the function's execution, and is being updated by var callback = arguments[lastIndex].

Does this behavior make sense? Im using the latest version of Chrome on OS X.

What's strange is that I only have problems when I concat this file with my other js files. If I run this script without concating them, the arguments array is never altered.

Is this some strange js bug, or am I missing something here. Perhaps the parameters should be removed from the emit function altogether, since they are never referred to anyways? This seems to fix my problem:

emit: function () {
  var lastIndex = arguments.length - 1;
  var callback = arguments[lastIndex];
  if(typeof callback == 'function') {
    callback = asyncAngularify(socket, callback);
    arguments[lastIndex] = callback;
  }
  return socket.emit.apply(socket, arguments);
}
@btford
Copy link
Owner

btford commented Apr 15, 2014

@jkirkwood maybe submit a PR with this change plus a test case?

Is this possibly because of a "use strict"?

@btford btford added the bug label Apr 15, 2014
@jkirkwood
Copy link
Contributor Author

Ah, that's it. From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode#Making_eval_and_arguments_simpler:

Second, strict mode code doesn't alias properties of arguments objects created within it. In normal code within a function whose first argument is arg, setting arg also sets arguments[0], and vice versa (unless no arguments were provided or arguments[0] is deleted). arguments objects for strict mode functions store the original arguments when the function was invoked. arguments[i] does not track the value of the corresponding named argument, nor does a named argument track the value in the corresponding arguments[i].

When I concat my js files, angular.js is at the top which starts with:

/**
 * @license AngularJS v1.2.16
 * (c) 2010-2014 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, document, undefined) {'use strict';

so 'use strict' is in the function scope, and not applied globally because it is not the first statement.

Should angular-socket-io also be modified to declare 'use strict' on the function scope? Like so?

angular.module('btford.socket-io', []).
  provider('socketFactory', function () {
    'use strict';
    ...

@btford
Copy link
Owner

btford commented Apr 15, 2014

Yep. would you like to put together a PR?

@btford
Copy link
Owner

btford commented May 1, 2014

Fixed in #55.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants