Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access function location programmatically

Is it possible in code to access ["[[FunctionLocation]]"] property that google chrome developer tools show when using console log on a function ?

like image 378
Sushruth Avatar asked Dec 14 '16 15:12

Sushruth


2 Answers

The answer, for now, is no.

The [[FunctionLocation]] property you see in Inspector is added in V8Debugger::internalProperties() in the debugger's C++ code, which uses another C++ function V8Debugger::functionLocation() to gather information about the function. functionLocation() then uses a number of V8-specific C++ APIs such as v8::Function::GetScriptLineNumber() and GetScriptColumnNumber() to find out the exact information.

All APIs described above are exclusively available to C++ code, not JavaScript code. In other words, JavaScript code on the webpage does not have direct access to this information.


However, you may be able to get access to the properties using a Chrome extension. More recently, the V8 JavaScript engine used by Chrome has added support to access these properties through the Chrome DevTools Protocol. In particular, you can get the internal properties through the Runtime.getProperties call. Additionally, it seems like Chrome extensions may be able to interact with the DevTools protocol through chrome.debugger.

A proof of concept for using the DevTools protocol in Node.js, which has direct access to the protocol using the Inspector built-in module (helpfully mentioned by Mohamed in their answer):

global.a = () => { /* test function */ };

const s = new (require('inspector').Session)();
s.connect();

let objectId;
s.post('Runtime.evaluate', { expression: 'a' }, (err, { result }) => {
  objectId = result.objectId;
});
s.post('Runtime.getProperties', { objectId }, (err, { internalProperties }) => {
  console.log(internalProperties);
});

yields

[
  {
    name: '[[FunctionLocation]]',
    value: {
      type: 'object',
      subtype: 'internal#location',
      value: [Object],
      description: 'Object'
    }
  },
  {
    name: '[[Scopes]]',
    value: {
      type: 'object',
      subtype: 'internal#scopeList',
      className: 'Array',
      description: 'Scopes[2]',
      objectId: '{"injectedScriptId":1,"id":24}'
    }
  }
]

with Node.js v12.3.1.

like image 112
Timothy Gu Avatar answered Oct 07 '22 17:10

Timothy Gu


I know that it has been a while when this question was posted. Now, I had the same problem. I need to access the function location on the runtime.

Fortunately, NodeJS did a great job by exposing some v8 internal properties through the inspector module.

I have written a small module called func-loc that helps to retrieve a function location on the runtime.

Example:

const { locate } = require('func-loc');

const fn = () => {
  console.log('Hello there');
};

(async () => {
  const result = await locate(fn);
  console.log(result);
  // Will result: { source: 'file://__BASE_FOLDER__/func-loc/this-file.js', line: 3, column: 12 }
})();

Hope that helps.

like image 6
Mohamed IDRISSI Avatar answered Oct 07 '22 17:10

Mohamed IDRISSI