0

I may have worded the title badly but I figure the best way to explain what I'm trying to do is to show an example...

So consider the following code:

var obj={}
Object.defineProperty(obj, "a", { get: function() { return 1 }, enumerable:true, configurable:true } )
Object.defineProperty(obj, "b", { get: function() { return 2 }, enumerable:true, configurable:true } )
Object.defineProperty(obj, "c", { get: function() { return 3 }, enumerable:true, configurable:true } )

var codeString="return obj.a + obj.b + obj.c"

var func=Function(codeString)

func()//6

I have an object with get properties and a function made from a string. What I would like to be able to do is when the function is run (func()) and specific get properties in the function are called i'd like to know the index in the string (codeString) where it is called from. Which I can use / report on in the get function.

So for example, when property b is called in obj obj.b in the function that would be, index is say, 19..

I'm not sure if this is possible and couldn't think of a way of doing this so thought I'd put it out there..

If this doesn't make sense then please say and I'll try to explain it better.. Thanks for any help you may have...

treeseal7
  • 739
  • 8
  • 22
  • `console.trace()`? – VLAZ Feb 17 '20 at 20:54
  • needs to be usable within the code, not the console. and although it shows the path it doesn't show the exact position. wasn't aware of it though and will certainly be useful for debugging in the future.. – treeseal7 Feb 17 '20 at 20:57
  • 1
    Why would you need the line number *in code* for anything other than debugging? This seems like [an XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) - your code should work without knowledge of line numbers. – VLAZ Feb 17 '20 at 20:59
  • its not for debugging. 'codestring' is dynamic and can be edited by the user. I want to be able to identify the certain parts of the string when certain events occur. the reasons are comlicated, but thats what i'm after – treeseal7 Feb 17 '20 at 21:03
  • you may have a point with the XY thing but i can't really think of a simpler way of explaining it without explaining the entire project, which is probably a bit excessive! – treeseal7 Feb 17 '20 at 21:05
  • 'Function' allows you to make a function from a string. This is needed because the function is created by the user – treeseal7 Feb 17 '20 at 21:07
  • 1
    You probably want to investigate Abstract Syntax Tree transformations. Using something like Babel's AST tools, you can probably accomplish this. But it won't be trivial. – Scott Sauyet Feb 17 '20 at 21:07
  • 2
    For straight forward `codeString` (assuming e.g. that any `obj` is always the object in question), you can parse the code string, and look for property access on `obj`. – ASDFGerte Feb 17 '20 at 21:09
  • you mean just by using maybe a regex to search the `codeString` for the specific property access points? – treeseal7 Feb 17 '20 at 21:12
  • @ASDFGerte: yes, but one person's idea of straightforward is another's idea of obfuscated! ... `(() => obj)()['foobar'.slice(-2, -1).toLowerCase()]` might look straightforward to some. – Scott Sauyet Feb 17 '20 at 21:12
  • 2
    With straight forward i mean explicitly: `obj` is always the object in question. Property access is only done by directly specifying the property, and not in any computed way. Tl;dr; the code is very simplistic, and the line could even be found by a regex. – ASDFGerte Feb 17 '20 at 21:14
  • That's plan B, but as you mention this does get harder when the it's not just obj, but also a whole bunch of other objects with unknown names. Which is how it'd be and also like you say also computed in other ways which doesn't call the property by the particular name. Which was why I was hoping for another option! oh well, that's probably what i'll have to try and do.. – treeseal7 Feb 17 '20 at 21:17
  • 1
    Code analysis for the general case is mathematically impossible. There are other ways to accomplish your task, but they are difficult to achieve. What comes to mind is e.g. writing a javascript engine in javascript, or injecting code around every operation in the codestring, to track the current line/col. – ASDFGerte Feb 17 '20 at 21:21
  • what do you mean specifically by 'injecting code around every operation in the codestring'? I think i understand how that could work but how would you identify where to inject the additional code? – treeseal7 Feb 17 '20 at 21:23
  • Would this just be a job for a regex to identify every break in the code where a new access could be? – treeseal7 Feb 17 '20 at 21:25
  • 1
    around every operation where you can. E.g. `1 + 1 + 1` are two operations, so you'd inject two function calls to something that keeps track which operation was last called. Result would maybe be something like `tracker(2), (tracker(1), 1 + 1) + 1`. When your getter is called, you know the last operation, and where in the codestring that is. It's an abomination to do, i'd think for days, whether there isn't an alternative, before doing something like that :D It was just a random idea that came to mind. – ASDFGerte Feb 17 '20 at 21:29
  • fair enough! seems like not a terrible idea.. but yeah implementing it successfully might be a pig! i might play with it for a bit and see if it's at all feasible.. either way made me think about the problem in a different way, so thanks for your thoughts.. – treeseal7 Feb 17 '20 at 21:33
  • 1
    If you are ok with non-standard features, you can [use an `Error`](https://stackoverflow.com/questions/1340872/how-to-get-javascript-caller-function-line-number-how-to-get-javascript-caller) inside your getter. On most engines, these have a `stack` property, which is basically a stack trace. It will therefore usually include the line/col of the caller, which is of the created function, where the string is usually just dumped in without much formatting (all non-standard, and may change at any day). Shouldn't be too hard to map this back to the position in the string. – ASDFGerte Feb 17 '20 at 21:47
  • that's an interesting idea.. I'll take a look into that too, thanks – treeseal7 Feb 17 '20 at 22:10

0 Answers0