Repository navigation
Conversation
| CHAKRA_API JsCreateObject(_Out_ JsValueRef *object) | ||
| { | ||
| return ContextAPINoScriptWrapper([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPIWrapper<true>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
Why do these calls need to change from ContextAPINoScriptWrapper to ContextAPIWrapper? Is this fixing a correctness bug? It looks to me like creating an object doesn't rely on executing any script.
There was a problem hiding this comment.
My thinking (explained a bit on PR comment) Don't we allocate memory?
There was a problem hiding this comment.
It does allocate memory yes, but ContextAPINoScriptWrapper sets up handlers for OOM exceptions (and I believe we also failfast on OOM as well) so I'm not sure why we specifically need the script-handling version here.
There was a problem hiding this comment.
@MSLaguana is right. JsCreateObject() won't execute the user script and hence we want to keep it under ContextAPINoScriptWrapper. Additionally ContextAPINoScriptWrapper is lighter version of ContextApiWrapper as it doesn't have BEGIN_ENTER_SCRIPT(scriptContext, true, true, true) and END_ENTER_SCRIPT.
There was a problem hiding this comment.
BTW, we do set up handler for OOM in both cases.
|
|
||
| CHAKRA_API JsInstanceOf(_In_ JsValueRef object, _In_ JsValueRef constructor, _Out_ bool *result) { | ||
| return ContextAPIWrapper<true>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPINoScriptWrapper([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
Are you sure that this is correct? It is possible to provide a custom hasInstance method which may have arbitrary side effects, so surely we need to allow for the possibility of script executing here?
There was a problem hiding this comment.
Yes right, I was 50/50 on this, will update
| return ContextAPINoScriptWrapper([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTHasProperty, (Js::PropertyRecord *)propertyId, object); | ||
|
|
||
| VALIDATE_INCOMING_OBJECT(object, scriptContext); |
There was a problem hiding this comment.
While you are modifying this area, I just noticed the line *hasProperty = nullptr which seems strange since hasProperty is a bool* so if anything we should be doing *hasProperty = false, or just removing that line completely and letting the following line set the value.
| CHAKRA_API JsHasIndexedProperty(_In_ JsValueRef object, _In_ JsValueRef index, _Out_ bool *result) | ||
| { | ||
| return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPINoScriptWrapper([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
I'm not convinced that this is safe, given the ability to write a proxy with a custom accessor.
| { | ||
| return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPINoScriptWrapper([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTEquals, object1, object2, false); |
There was a problem hiding this comment.
This can also call script if one of the objects has a custom valueOf provided.
| CHAKRA_API JsStrictEquals(_In_ JsValueRef object1, _In_ JsValueRef object2, _Out_ bool *result) | ||
| { | ||
| return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPINoScriptWrapper([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
I believe that this one is probably fine.
|
|
||
| CHAKRA_API JsGetPrototype(_In_ JsValueRef object, _Out_ JsValueRef *prototypeObject) | ||
| { | ||
| return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
ContextAPIWrapper [](start = 11, length = 17)
can call user script code if have getter?
| @@ -1342,7 +1342,7 @@ CHAKRA_API JsInstanceOf(_In_ JsValueRef object, _In_ JsValueRef constructor, _Ou | |||
|
|
|||
| CHAKRA_API JsGetExtensionAllowed(_In_ JsValueRef object, _Out_ bool *value) | |||
There was a problem hiding this comment.
JsGetExtensionAllowed [](start = 11, length = 21)
For most of the APIs below can call into user code if the object is proxy and you have handler for respective methods. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
When JSRT call ends up creating an object etc. (recycler allocation) we better wrap using ContextAPIWrapper. Oppositely, we could use a lighter version of it (ContextAPINoScriptWrapper) for simpler tasks
| *hasProperty = nullptr; | ||
| *hasProperty = false; | ||
|
|
||
| *hasProperty = Js::JavascriptOperators::OP_HasProperty(object, ((Js::PropertyRecord *)propertyId)->GetPropertyId(), scriptContext) != 0; |
There was a problem hiding this comment.
I'm curious now, how does OP_HasProperty interact with proxies? It looks like it walks the prototype chain, but I'm not sure whether it can potentially trigger proxies (e.g. custom get functions on the proxy) or if it only checks for normal properties.
There was a problem hiding this comment.
Yes, I will double check this because I see OP_HasProperty calls into HasPropertyQuery and Proxy has an implementation for it.
In reply to: 126565457 [](ancestors = 126565457)
There was a problem hiding this comment.
Well, don't spend much time on this. I've been working on another approach that might cover the rest as well. I will close this PR for now.
| CHAKRA_API JsDefineProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propertyId, _In_ JsValueRef propertyDescriptor, _Out_ bool *result) | ||
| { | ||
| return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { | ||
| return ContextAPINoScriptWrapper([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode { |
There was a problem hiding this comment.
DefineOwnPropertyDescriptor can also be proxied.
When JSRT call ends up creating an object etc. (recycler allocation) we better wrap using ContextAPIWrapper. Oppositely, we could use a lighter version of it (ContextAPINoScriptWrapper) for simpler tasks.
Especially JsHasProperty is a very hot call for node-chakracore.