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

How to alter a CallSite? #7

Open
julien-f opened this issue Oct 13, 2015 · 6 comments
Open

How to alter a CallSite? #7

julien-f opened this issue Oct 13, 2015 · 6 comments

Comments

@julien-f
Copy link

I am currently writing a modifier for stack-chain to enable source maps in Node and I need to alter some call sites to fix the filename, the line and the column.

Unfortunately, the CallSite#toString() is read-only, any ideas?

'use strict'

function getCallSite () {
  // Save original values.
  var stackTraceLimit = Error.stackTraceLimit
  var prepareStackTrace = Error.prepareStackTrace

  // Make the changes.
  Error.stackTraceLimit = 2
  Error.prepareStackTrace = function (_, callSites) {
    return callSites[1]
  }

  // Get the call site.
  var callSite = new Error().stack

  // Restore the original values.
  Error.stackTraceLimit = stackTraceLimit
  Error.prepareStackTrace = prepareStackTrace

  return callSite
}

var callSite = getCallSite()

callSite.getFilename = function () {
  return 'foo.js'
}

console.log(callSite.toString())

Expected result:

Object.<anonymous> (foo.js:22:16)

Actual result:

callSite.getFileName = function () {
                     ^

TypeError: Cannot assign to read only property 'getFileName' of [object Object]
    at Object.<anonymous> (/tmp/index.js:26:22)
    at Module._compile (module.js:434:26)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3

I also tried to clone the callSite object, but this time, the toString() method throws an illegal access error:

var copy = Object.create(callSite, {
  getFileName: {
    value: function () {
      return 'foo.js'
    }
  }
})

console.log(copy.toString())
@julien-f
Copy link
Author

The work around currently used in source-map-support is to reimplement the toString() method, which looks pretty bad to me :/

@AndreasMadsen
Copy link
Owner

Hmm. I have never done that before. Looking quickly at it, it seams like defining your own CallSite object from scratch is the only way. (the CallSite object is defined here https://github.com/v8/v8/blob/263340113713db788e56abda61062dd9513b9f79/src/js/messages.js#L593L749)

I will have to investigate it more, but I don't think there is anything that can be done.

@julien-f
Copy link
Author

Maybe stack-chain should provide an utility function to clone a CallSite with a custom toString().

It's far from perfect but at least it avoids the need to duplicate this code for each stack modifier :/

@AndreasMadsen
Copy link
Owner

I think a mutate helper in general would be nice. But I wouldn't restrict it to just toString()

@AndreasMadsen
Copy link
Owner

I would welcome a CustomCallSite constructor that looks like:

CustomCallSite(callSite, {
  fileName: 'script.coffee',
  // other overwritten properties
});

It would the have the v8-defined get and is functions, which uses the custom properties (in second argument) and defaults to using the callSite object. At last it would provide the v8-standard toString function that formats the CustomCallSite object.

Eventually I might do this myself, but I would suggests that you make a pull request.

@julien-f
Copy link
Author

Ok, I don't have much time for it currently but maybe one day :)

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

No branches or pull requests

2 participants