0

In the Azure Pipelines task library, there is a call to path.resolve() via apply() that I don't really understand:

var absolutePath = path.resolve.apply(this, pathSegments);

where pathSegments: any[]

The above code is within an function exported at module scope, so (if I understand correctly) this will refer to the module itself. But I'm at a loss as to what is the effect of calling via apply rather than just calling path.resolve() directly. Can anyone explain?

Context: I suspect this may be something related to mocking - there is a similar function in the equivalent mock module, which uses path.posix.resolve.apply(). My underlying issue is that when I call the mocked tl.resolve('') - indirectly via tl.filePathSupplied() - it returns the actual cwd rather than the one mocked via TaskLibAnswers.

Rich Tebb
  • 6,806
  • 2
  • 23
  • 25

1 Answers1

2

The .apply() method on any function gives you two features:

  1. It lets you set the this value when the function is called.
  2. It lets you pass an arbitrary array of arguments that will be unpacked into actual arguments (not in an array) when the function is called.

In this case, it is likely feature #2 that it is being used for here because path.resolve() accepts an arbitrary number of arguments. If you're not using the latest versions of node.js or coding to a lower level of Javascript support and thus don't have the spread operator, then .apply() would be the natural way to pass an arbitrary number of arguments to a function when the arguments were passed to you in an array.

If you look at the source for the path module and find the code for the resolve() function, you will find that it does not use a this value at all so the path object is used ONLY as a namespace object. Thus, you can send any value of this you want into the resolve function and it will make no difference.

So, probably, the code is using .apply() not so that it can set the value of this, but so that it can pass an arbitrary array of arguments to the function.

But I'm at a loss as to what is the effect of calling via apply rather than just calling path.resolve() directly. Can anyone explain?

If you showed us more of the surrounding code, we could answer with more certainty, but it seems likely that the pathSegments variable is already an array of path values that this code wants to pass to path.resolve(). If that's an arbitrary array, then the two simplest ways to pass that array as separate arguments to path.resolve() are:

path.resolve.apply(path, pathSegments)

and

path.resolve(...pathSegments)

If this code was written with an older target in mind that did not have the ... syntax, then the .apply() option would be the simplest way to do it.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • It's definitely being used as an alternative to the spread operator, given the context (which was in the link I provided, but your assumption was spot on). – Rich Tebb Feb 24 '20 at 09:12