Using 'this' in scripts

59 views
Skip to first unread message

Zoltan B

unread,
Jun 7, 2019, 7:16:08 AM6/7/19
to v8-users
Hi!

Is there a way to provide value for the 'this' keyword, when I'm running a v8 Script? 

An alternative would be to compile the code as a function instead, and provide 'this' when calling it trough 'recv', but then I would have other issues: running a script like this: "1+1" would not return 2 as a result, as I would have to explicitly put a "return" in front of "1+1", so the function will return the script's value. This seems to be error prone, not to mention that script locations will skew when viewed from DevTools. Using "return eval('1+1')" would work, but it kills performance due to the eval.

Zoltan B

unread,
Jun 20, 2019, 9:49:19 AM6/20/19
to v8-users
Any ideas? :)

Caitlin Potter

unread,
Jun 20, 2019, 10:04:53 AM6/20/19
to v8-u...@googlegroups.com
I don’t believe you can do exactly what you want here, as there are two parts:

1) getting `this` set properly. I believe you should be able to use `CompileFunctionInContext()` to this effect, which is used to provide implicit arguments to DOM onxxx=“script...” handlers. I believe you can then make `this` whatever you want in that function. Return statements would still be legal, as they are in DOM events, though.

2) completion value of the script. This is trickier, as the v8 API does not expose a way to run the AST rewriter on arbitrary functions afaict. It may be possible to introduce an API for this, if it’s important.

You might be able to take a third option, transforming the code with a custom Babel plugin before passing it to v8 (at runtime), and providing the sourcemap info along with it for debugging purposes.
--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/746a4d9f-d364-4506-8783-347eee5dad6c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Zoltan B

unread,
Jun 21, 2019, 3:27:41 AM6/21/19
to v8-users
Thanks for your answer! :)

In the (1) solution of yours, is there a way to be able to create functions that behave like scripts? I mean, that if I write onclick="1+1", then if I parse and run "1+1" as a function it would return 2 without using the "return" keyword (e.g.: "return 1+1")?


2019. június 20., csütörtök 16:04:53 UTC+2 időpontban Caitlin Potter a következőt írta:
I don’t believe you can do exactly what you want here, as there are two parts:

1) getting `this` set properly. I believe you should be able to use `CompileFunctionInContext()` to this effect, which is used to provide implicit arguments to DOM onxxx=“script...” handlers. I believe you can then make `this` whatever you want in that function. Return statements would still be legal, as they are in DOM events, though.

2) completion value of the script. This is trickier, as the v8 API does not expose a way to run the AST rewriter on arbitrary functions afaict. It may be possible to introduce an API for this, if it’s important.

You might be able to take a third option, transforming the code with a custom Babel plugin before passing it to v8 (at runtime), and providing the sourcemap info along with it for debugging purposes.

On Jun 20, 2019, at 9:49 AM, Zoltan B <zben...@gmail.com> wrote:

Any ideas? :)

2019. június 7., péntek 13:16:08 UTC+2 időpontban Zoltan B a következőt írta:
Hi!

Is there a way to provide value for the 'this' keyword, when I'm running a v8 Script? 

An alternative would be to compile the code as a function instead, and provide 'this' when calling it trough 'recv', but then I would have other issues: running a script like this: "1+1" would not return 2 as a result, as I would have to explicitly put a "return" in front of "1+1", so the function will return the script's value. This seems to be error prone, not to mention that script locations will skew when viewed from DevTools. Using "return eval('1+1')" would work, but it kills performance due to the eval.

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-u...@googlegroups.com.

Caitlin Potter

unread,
Jun 21, 2019, 4:01:47 AM6/21/19
to v8-u...@googlegroups.com
No, that method would still require a return statement. Getting rid of the return statement requirement would need a new API, or transforming the source program before using it.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/edc28096-a090-4188-9828-11ed67ddd6c1%40googlegroups.com.

Zoltan B

unread,
Jun 21, 2019, 5:56:47 AM6/21/19
to v8-users
Thank you!

Also, In the case I'm running a Script (and not a function), if I write "myvariable" or "this.myvariable" then is there a way to distuingish between the two in the C++ side? Currently how I'm using it is like this: The context the script runs in has a global object with my template, so that I can provide external name resolution for contexts. However "myvariable" and "this.myvariable" both call the same global object, so if I could distuingish between the two, I could provide separate name resolution for 'this' and contextual variables.


2019. június 21., péntek 10:01:47 UTC+2 időpontban Caitlin Potter a következőt írta:
No, that method would still require a return statement. Getting rid of the return statement requirement would need a new API, or transforming the source program before using it.

J Decker

unread,
Jun 21, 2019, 7:18:51 AM6/21/19
to v8-u...@googlegroups.com
I run scripts to extend a 'this', but when that script runs, it just iniializes this.whatever and provides methods like this.handleMessage = function() {}

If I want the object initilaized with the script to give me a value, I'd call a method on the this, but I don't know that the initialization code would really return any value.  Maybe I'm just biased because I consider that script a 'constructor()' which doesn't return, but instead just defines the methods on the object specified....

   var objectForThis = {};
   var script = "   \
            this.method = ()=>{    \
                console.log( "stuff" );    \
               return 6+3; \
             }; \
            var closureVariablesWorkToo = 33; "

    var f = new Function( /* function args */ "JSON", "localStorage", script );
    f.call( objectForThis, JSON, localStorage /*, ... extra args */ );

    var result1 =   objectForThis.method();



//   ---- This might be a way of providing getter and setter on the 'this' so you can know if 'myvariable' is accessed...

   var anotherScript = `  
       const scriptMethods = {
            method() {    
                console.log( "stuff" );    
               return 6+3; 
             }, 
             get Getter() {
                     return 'getter value';
             },
             set Getter(val) {
                     console.log( 'save setter value' );
             }
       }; 

      Object.defineProperties( this, Object.getOwnPropertyDescriptors( scriptMethods ));  ";
        

But; go go back to the start, what value would you want to return from a constructor other than the constructed 'this'?


To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/44b2bf8b-888c-4dc9-bc21-e0b570f4d9c2%40googlegroups.com.

J Decker

unread,
Jun 21, 2019, 11:00:52 PM6/21/19
to v8-u...@googlegroups.com

Sorry I did reflect that there's probably cases of simpler expessions.
You could limit it to just no semicolons, and only allow commas, then you could just put it in a `()=>(/*expression without return*/)`
but that doesn't let you pass a this.

so you could make a  `function() { return ` + (your expression ) + ` } `  could get a 'this'.
In the V8 engine though, args do have 'Holder()' and 'This()' and I'm not entirely sure how they differ, but most of my code is actually using Holder() to unwrap and get my object from.

Zoltan B

unread,
Jun 24, 2019, 3:35:44 AM6/24/19
to v8-users
thanks, I'm struggling between function() { return ( "expression" ) } and running a script like: with(myContextProxy){ "expression" }. The latter allows me to handle this.x and x resolution separately as well but has other drawbacks (this is still not the object I want it to be so I cant put it into a storage, also functions created in the expression will store the wrong 'this'... so its not an easy issue :) 

Reply all
Reply to author
Forward
0 new messages