mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Javascript: Split implementation across multiple files
This commit is contained in:
parent
867d642872
commit
78ca2c5341
19 changed files with 1400 additions and 1088 deletions
|
|
@ -2522,9 +2522,14 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_javascript/choc/text/choc_StringUtilities.h"
|
||||
"../../../../../modules/juce_javascript/choc/text/choc_UTF8.h"
|
||||
"../../../../../modules/juce_javascript/choc/LICENSE.md"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript.h"
|
||||
"../../../../../modules/juce_javascript/detail/juce_QuickJSHelpers.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript_test.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JavascriptEngine.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JavascriptEngine.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSCursor.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSCursor.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSObject.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSObject.h"
|
||||
"../../../../../modules/juce_javascript/juce_javascript.cpp"
|
||||
"../../../../../modules/juce_javascript/juce_javascript.h"
|
||||
"../../../../../modules/juce_opengl/geometry/juce_Draggable3DOrientation.h"
|
||||
|
|
@ -5112,9 +5117,14 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_javascript/choc/text/choc_StringUtilities.h"
|
||||
"../../../../../modules/juce_javascript/choc/text/choc_UTF8.h"
|
||||
"../../../../../modules/juce_javascript/choc/LICENSE.md"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript.h"
|
||||
"../../../../../modules/juce_javascript/detail/juce_QuickJSHelpers.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_Javascript_test.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JavascriptEngine.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JavascriptEngine.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSCursor.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSCursor.h"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSObject.cpp"
|
||||
"../../../../../modules/juce_javascript/javascript/juce_JSObject.h"
|
||||
"../../../../../modules/juce_javascript/juce_javascript.cpp"
|
||||
"../../../../../modules/juce_javascript/juce_javascript.h"
|
||||
"../../../../../modules/juce_opengl/geometry/juce_Draggable3DOrientation.h"
|
||||
|
|
|
|||
|
|
@ -3092,10 +3092,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -4644,7 +4650,10 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_JSON.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_StringUtilities.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_opengl\geometry\juce_Draggable3DOrientation.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_opengl\geometry\juce_Matrix3D.h"/>
|
||||
|
|
|
|||
|
|
@ -764,6 +764,9 @@
|
|||
<Filter Include="JUCE Modules\juce_javascript\choc">
|
||||
<UniqueIdentifier>{D2777265-A166-EDB8-938A-47D1EDAADA42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\detail">
|
||||
<UniqueIdentifier>{D98D147D-FDDB-12D7-2C59-B686F458CE18}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\javascript">
|
||||
<UniqueIdentifier>{AF145034-7775-F013-E219-381BA369C108}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
|
@ -3934,10 +3937,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.mm">
|
||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -8367,7 +8376,16 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h">
|
||||
<Filter>JUCE Modules\juce_javascript\choc\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h">
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h">
|
||||
<Filter>JUCE Modules\juce_javascript\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h">
|
||||
|
|
|
|||
|
|
@ -3092,10 +3092,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -4644,7 +4650,10 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_JSON.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_StringUtilities.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_opengl\geometry\juce_Draggable3DOrientation.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_opengl\geometry\juce_Matrix3D.h"/>
|
||||
|
|
|
|||
|
|
@ -764,6 +764,9 @@
|
|||
<Filter Include="JUCE Modules\juce_javascript\choc">
|
||||
<UniqueIdentifier>{D2777265-A166-EDB8-938A-47D1EDAADA42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\detail">
|
||||
<UniqueIdentifier>{D98D147D-FDDB-12D7-2C59-B686F458CE18}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\javascript">
|
||||
<UniqueIdentifier>{AF145034-7775-F013-E219-381BA369C108}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
|
@ -3934,10 +3937,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.mm">
|
||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -8367,7 +8376,16 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h">
|
||||
<Filter>JUCE Modules\juce_javascript\choc\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h">
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h">
|
||||
<Filter>JUCE Modules\juce_javascript\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h">
|
||||
|
|
|
|||
|
|
@ -2927,10 +2927,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -4444,7 +4450,10 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_JSON.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_StringUtilities.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_midi_ci\ci\juce_CIChannelAddress.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_midi_ci\ci\juce_CIDevice.h"/>
|
||||
|
|
|
|||
|
|
@ -716,6 +716,9 @@
|
|||
<Filter Include="JUCE Modules\juce_javascript\choc">
|
||||
<UniqueIdentifier>{D2777265-A166-EDB8-938A-47D1EDAADA42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\detail">
|
||||
<UniqueIdentifier>{D98D147D-FDDB-12D7-2C59-B686F458CE18}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\javascript">
|
||||
<UniqueIdentifier>{AF145034-7775-F013-E219-381BA369C108}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
|
@ -3706,10 +3709,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.mm">
|
||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -7971,7 +7980,16 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h">
|
||||
<Filter>JUCE Modules\juce_javascript\choc\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h">
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h">
|
||||
<Filter>JUCE Modules\juce_javascript\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h">
|
||||
|
|
|
|||
|
|
@ -2927,10 +2927,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -4444,7 +4450,10 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_JSON.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_StringUtilities.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_midi_ci\ci\juce_CIChannelAddress.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_midi_ci\ci\juce_CIDevice.h"/>
|
||||
|
|
|
|||
|
|
@ -716,6 +716,9 @@
|
|||
<Filter Include="JUCE Modules\juce_javascript\choc">
|
||||
<UniqueIdentifier>{D2777265-A166-EDB8-938A-47D1EDAADA42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\detail">
|
||||
<UniqueIdentifier>{D98D147D-FDDB-12D7-2C59-B686F458CE18}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="JUCE Modules\juce_javascript\javascript">
|
||||
<UniqueIdentifier>{AF145034-7775-F013-E219-381BA369C108}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
|
@ -3706,10 +3709,16 @@
|
|||
<ClCompile Include="..\..\..\..\modules\juce_gui_extra\juce_gui_extra.mm">
|
||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript_test.cpp">
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.cpp">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\modules\juce_javascript\juce_javascript.cpp">
|
||||
|
|
@ -7971,7 +7980,16 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_javascript\choc\text\choc_UTF8.h">
|
||||
<Filter>JUCE Modules\juce_javascript\choc\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_Javascript.h">
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\detail\juce_QuickJSHelpers.h">
|
||||
<Filter>JUCE Modules\juce_javascript\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JavascriptEngine.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSCursor.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\javascript\juce_JSObject.h">
|
||||
<Filter>JUCE Modules\juce_javascript\javascript</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_javascript\juce_javascript.h">
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
namespace juce::detail
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -45,7 +45,7 @@ template <typename T>
|
|||
static int64_t toJuceInt64 (const T& convertible) { return (int64) (int64_t) convertible; }
|
||||
|
||||
//==============================================================================
|
||||
namespace qjs = detail::choc::javascript::quickjs;
|
||||
namespace qjs = choc::javascript::quickjs;
|
||||
|
||||
using VarOrError = std::variant<var, String>;
|
||||
|
||||
|
|
@ -401,7 +401,7 @@ static VarOrError quickJSToJuce (const qjs::QuickJSContext::ValuePtr& ptr)
|
|||
{
|
||||
return tryQuickJSToJuce (ptr);
|
||||
}
|
||||
catch (const detail::choc::javascript::Error& error)
|
||||
catch (const choc::javascript::Error& error)
|
||||
{
|
||||
return String (error.what());
|
||||
}
|
||||
|
|
@ -412,7 +412,7 @@ static VarOrError quickJSToJuce (const qjs::QuickJSContext::ValuePtr& ptr)
|
|||
// this with GCC. Suppressing this warning is fine, since these classes are only visible and used
|
||||
// in a single translation unit.
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wsubobject-linkage")
|
||||
class detail::QuickJSWrapper
|
||||
class QuickJSWrapper
|
||||
{
|
||||
public:
|
||||
qjs::JSContext* getQuickJSContext() const
|
||||
|
|
@ -589,221 +589,12 @@ struct DynamicObjectWrapper
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
detail::QuickJSWrapper& engine;
|
||||
QuickJSWrapper& engine;
|
||||
DynamicObject::Ptr object;
|
||||
std::map<Identifier, int16_t> ordinals;
|
||||
std::vector<Identifier> identifiers;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class JavascriptEngine::Impl
|
||||
{
|
||||
public:
|
||||
using ValuePtr = qjs::QuickJSContext::ValuePtr;
|
||||
|
||||
//==============================================================================
|
||||
Impl()
|
||||
{
|
||||
DynamicObjectWrapper::createClass (engine.getQuickJSRuntime());
|
||||
|
||||
engine.setInterruptHandler ([this]
|
||||
{
|
||||
return (int64) Time::getMillisecondCounterHiRes() >= timeout;
|
||||
});
|
||||
}
|
||||
|
||||
void registerNativeObject (const Identifier& name,
|
||||
DynamicObject::Ptr dynamicObject,
|
||||
std::optional<qjs::JSValue> parent = std::nullopt)
|
||||
{
|
||||
auto wrapper = std::make_unique<DynamicObjectWrapper> (engine, dynamicObject);
|
||||
auto* ctx = engine.getQuickJSContext();
|
||||
auto jsObject = JS_NewObjectClass (ctx, (int) DynamicObjectWrapper::getClassId());
|
||||
qjs::JS_SetOpaque (jsObject, (void*) wrapper.get());
|
||||
|
||||
std::vector<qjs::JSCFunctionListEntry> propertyFunctionList;
|
||||
|
||||
for (const auto& [identifier, prop] : wrapper->getProperties())
|
||||
{
|
||||
auto* jsIdentifier = identifier.toString().toRawUTF8();
|
||||
|
||||
if (prop.isMethod())
|
||||
{
|
||||
qjs::JS_SetPropertyStr (ctx,
|
||||
jsObject,
|
||||
jsIdentifier,
|
||||
JS_NewCFunctionMagic (ctx,
|
||||
DynamicObjectWrapper::callDispatcher,
|
||||
jsIdentifier,
|
||||
0,
|
||||
qjs::JS_CFUNC_generic_magic,
|
||||
wrapper->getOrdinal (identifier)));
|
||||
}
|
||||
else if (prop.isObject())
|
||||
{
|
||||
if (auto* embeddedObject = prop.getDynamicObject())
|
||||
registerNativeObject (identifier, embeddedObject, jsObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto entry = makeFunctionListEntry (jsIdentifier,
|
||||
DynamicObjectWrapper::getDispatcher,
|
||||
DynamicObjectWrapper::setDispatcher,
|
||||
wrapper->getOrdinal (identifier));
|
||||
propertyFunctionList.push_back (entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (! propertyFunctionList.empty())
|
||||
{
|
||||
qjs::JS_SetPropertyFunctionList (ctx,
|
||||
jsObject,
|
||||
propertyFunctionList.data(),
|
||||
(int) propertyFunctionList.size());
|
||||
}
|
||||
|
||||
const auto jsObjectName = name.toString().toRawUTF8();
|
||||
|
||||
if (parent.has_value())
|
||||
{
|
||||
qjs::JS_SetPropertyStr (ctx, *parent, jsObjectName, jsObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
ValuePtr globalObject { qjs::JS_GetGlobalObject (ctx), ctx };
|
||||
qjs::JS_SetPropertyStr (ctx, globalObject.get(), jsObjectName, jsObject);
|
||||
}
|
||||
|
||||
wrapper.release();
|
||||
}
|
||||
|
||||
var evaluate (const String& code, Result* errorMessage, RelativeTime maxExecTime)
|
||||
{
|
||||
resetTimeout (maxExecTime);
|
||||
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::ok();
|
||||
|
||||
const auto result = quickJSToJuce ({ JS_Eval (engine.getQuickJSContext(), code.toRawUTF8(), code.getNumBytesAsUTF8(), "", JS_EVAL_TYPE_GLOBAL), engine.getQuickJSContext() });
|
||||
|
||||
if (auto* v = std::get_if<var> (&result))
|
||||
return *v;
|
||||
|
||||
if (auto* e = std::get_if<String> (&result))
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::fail (*e);
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
Result execute (const String& code, RelativeTime maxExecTime)
|
||||
{
|
||||
auto result = Result::ok();
|
||||
evaluate (code, &result, maxExecTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
var callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage,
|
||||
RelativeTime maxExecTime)
|
||||
{
|
||||
resetTimeout (maxExecTime);
|
||||
|
||||
auto* ctx = engine.getQuickJSContext();
|
||||
const auto functionStr = function.toString();
|
||||
|
||||
const auto fn = qjs::JS_NewAtomLen (ctx, functionStr.toRawUTF8(), functionStr.getNumBytesAsUTF8());
|
||||
|
||||
JSFunctionArguments argList { ctx, args };
|
||||
|
||||
qjs::QuickJSContext::ValuePtr global { JS_GetGlobalObject (ctx), ctx };
|
||||
qjs::QuickJSContext::ValuePtr returnVal { JS_Invoke (ctx, global.get(), fn, argList.getSize(), argList.getArguments()), ctx };
|
||||
|
||||
JS_FreeAtom (ctx, fn);
|
||||
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::ok();
|
||||
|
||||
const auto result = quickJSToJuce (returnVal);
|
||||
|
||||
if (auto* v = std::get_if<var> (&result))
|
||||
return *v;
|
||||
|
||||
if (auto* e = std::get_if<String> (&result))
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::fail (*e);
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
void stop() noexcept
|
||||
{
|
||||
timeout = (int64) Time::getMillisecondCounterHiRes();
|
||||
}
|
||||
|
||||
JSObject getRootObject() const
|
||||
{
|
||||
return JSObject { &engine };
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void resetTimeout (RelativeTime maxExecTime)
|
||||
{
|
||||
timeout = (int64) Time::getMillisecondCounterHiRes() + maxExecTime.inMilliseconds();
|
||||
}
|
||||
|
||||
detail::QuickJSWrapper engine;
|
||||
std::atomic<int64> timeout{};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
JavascriptEngine::JavascriptEngine()
|
||||
: maximumExecutionTime (15.0),
|
||||
impl (std::make_unique<Impl>())
|
||||
{
|
||||
}
|
||||
|
||||
JavascriptEngine::~JavascriptEngine() = default;
|
||||
|
||||
void JavascriptEngine::registerNativeObject (const Identifier& name, DynamicObject* object)
|
||||
{
|
||||
impl->registerNativeObject (name, object);
|
||||
}
|
||||
|
||||
Result JavascriptEngine::execute (const String& javascriptCode)
|
||||
{
|
||||
return impl->execute (javascriptCode, maximumExecutionTime);
|
||||
}
|
||||
|
||||
var JavascriptEngine::evaluate (const String& javascriptCode, Result* errorMessage)
|
||||
{
|
||||
return impl->evaluate (javascriptCode, errorMessage, maximumExecutionTime);
|
||||
}
|
||||
|
||||
var JavascriptEngine::callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage)
|
||||
{
|
||||
return impl->callFunction (function, args, errorMessage, maximumExecutionTime);
|
||||
}
|
||||
|
||||
void JavascriptEngine::stop() noexcept
|
||||
{
|
||||
impl->stop();
|
||||
}
|
||||
|
||||
JSObject JavascriptEngine::getRootObject() const
|
||||
{
|
||||
return impl->getRootObject();
|
||||
}
|
||||
|
||||
NamedValueSet JavascriptEngine::getRootObjectProperties() const
|
||||
{
|
||||
return getRootObject().getProperties();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool hasProperty (qjs::JSContext* ctx, qjs::JSValueConst object, const char* name)
|
||||
{
|
||||
|
|
@ -827,433 +618,4 @@ static uint32_t toUint32 (int64 value)
|
|||
return (uint32_t) value;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wsubobject-linkage")
|
||||
class JSObject::Impl
|
||||
{
|
||||
public:
|
||||
using ValuePtr = qjs::QuickJSContext::ValuePtr;
|
||||
|
||||
explicit Impl (const detail::QuickJSWrapper* engineIn)
|
||||
: Impl (engineIn,
|
||||
{ qjs::JS_GetGlobalObject (engineIn->getQuickJSContext()), engineIn->getQuickJSContext() })
|
||||
{
|
||||
}
|
||||
|
||||
Impl (const Impl& other)
|
||||
: Impl (other.engine,
|
||||
{ qjs::JS_DupValue (other.engine->getQuickJSContext(), other.valuePtr.get()),
|
||||
other.engine->getQuickJSContext() })
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Impl> getChild (const Identifier& prop) const
|
||||
{
|
||||
return rawToUniquePtr (new Impl (engine, { getOrCreateProperty (engine->getQuickJSContext(),
|
||||
valuePtr.get(),
|
||||
prop.toString().toRawUTF8()),
|
||||
engine->getQuickJSContext() }));
|
||||
}
|
||||
|
||||
std::unique_ptr<Impl> getChild (int64 index) const
|
||||
{
|
||||
jassert (isArray());
|
||||
return rawToUniquePtr (new Impl (engine, valuePtr[toUint32 (index)]));
|
||||
}
|
||||
|
||||
bool hasProperty (const Identifier& name) const
|
||||
{
|
||||
return juce::hasProperty (engine->getQuickJSContext(), valuePtr.get(), name.toString().toRawUTF8());
|
||||
}
|
||||
|
||||
void setProperty (const Identifier& name, const var& value) const
|
||||
{
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
|
||||
qjs::JS_SetPropertyStr (ctx, valuePtr.get(), name.toString().toRawUTF8(), juceToQuickJs (value, ctx));
|
||||
}
|
||||
|
||||
void setProperty (int64 index, const var& value) const
|
||||
{
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
|
||||
qjs::JS_SetPropertyInt64 (ctx, valuePtr.get(), index, juceToQuickJs (value, ctx));
|
||||
}
|
||||
|
||||
var get() const
|
||||
{
|
||||
if (auto* opaque = qjs::JS_GetOpaque (valuePtr.get(), DynamicObjectWrapper::getClassId()))
|
||||
if (DynamicObjectWrapper::getDynamicObjects().count (opaque) != 0)
|
||||
return { static_cast<DynamicObjectWrapper*> (opaque)->object.get() };
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
return discardError (quickJSToJuce ({ qjs::JS_DupValue (ctx, valuePtr.get()), ctx }));
|
||||
}
|
||||
|
||||
VarOrError invokeMethod (const Identifier& methodName, Span<const var> args) const
|
||||
{
|
||||
if (! hasProperty (methodName))
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
const auto methodAtom = JS_NewAtom (ctx, methodName.toString().toRawUTF8());
|
||||
ScopeGuard scope { [&] { qjs::JS_FreeAtom (ctx, methodAtom); } };
|
||||
|
||||
JSFunctionArguments arguments { ctx, args };
|
||||
|
||||
ValuePtr returnVal { qjs::JS_Invoke (ctx,
|
||||
valuePtr.get(),
|
||||
methodAtom,
|
||||
arguments.getSize(),
|
||||
arguments.getArguments()),
|
||||
ctx };
|
||||
|
||||
return quickJSToJuce (returnVal);
|
||||
}
|
||||
|
||||
NamedValueSet getProperties() const
|
||||
{
|
||||
NamedValueSet result;
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
ValuePtr names { qjs::JS_GetOwnPropertyNames2 (ctx,
|
||||
valuePtr.get(),
|
||||
qjs::JS_GPN_ENUM_ONLY | qjs::JS_GPN_STRING_MASK,
|
||||
qjs::JS_ITERATOR_KIND_KEY),
|
||||
ctx };
|
||||
|
||||
|
||||
if (auto v = discardError (quickJSToJuce (names)); const auto* propertyNames = v.getArray())
|
||||
{
|
||||
for (const auto& name : *propertyNames)
|
||||
{
|
||||
if (name.isString())
|
||||
{
|
||||
const Identifier prop { name.toString() };
|
||||
result.set (prop, getChild (prop)->get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return qjs::JS_IsArray (engine->getQuickJSContext(), valuePtr.get());
|
||||
}
|
||||
|
||||
int64 getSize() const
|
||||
{
|
||||
if (! isArray())
|
||||
{
|
||||
jassertfalse;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto lengthProp = valuePtr["length"];
|
||||
uint32_t length = 0;
|
||||
qjs::JS_ToUint32 (engine->getQuickJSContext(), &length, lengthProp.get());
|
||||
return (int64) length;
|
||||
}
|
||||
|
||||
private:
|
||||
Impl (const detail::QuickJSWrapper* e, ValuePtr&& ptr)
|
||||
: engine (e), valuePtr (std::move (ptr))
|
||||
{
|
||||
}
|
||||
|
||||
const detail::QuickJSWrapper* engine = nullptr;
|
||||
ValuePtr valuePtr;
|
||||
};
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
JSObject::JSObject (const detail::QuickJSWrapper* engine)
|
||||
: impl (new Impl (engine))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::JSObject (std::unique_ptr<Impl> implIn)
|
||||
: impl (std::move (implIn))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::JSObject (const JSObject& other)
|
||||
: impl (new Impl (*other.impl))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::~JSObject() = default;
|
||||
|
||||
JSObject::JSObject (JSObject&&) noexcept = default;
|
||||
|
||||
JSObject& JSObject::operator= (const JSObject& other)
|
||||
{
|
||||
JSObject { other }.swap (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSObject& JSObject::operator= (JSObject&& other) noexcept = default;
|
||||
|
||||
JSObject JSObject::getChild (const Identifier& name) const
|
||||
{
|
||||
return JSObject { impl->getChild (name) };
|
||||
}
|
||||
|
||||
JSObject JSObject::operator[] (const Identifier& name) const
|
||||
{
|
||||
return getChild (name);
|
||||
}
|
||||
|
||||
bool JSObject::isArray() const
|
||||
{
|
||||
return impl->isArray();
|
||||
}
|
||||
|
||||
int64 JSObject::getSize() const
|
||||
{
|
||||
return impl->getSize();
|
||||
}
|
||||
|
||||
JSObject JSObject::getChild (int64 index) const
|
||||
{
|
||||
jassert (isArray());
|
||||
return JSObject { impl->getChild (index) };
|
||||
}
|
||||
|
||||
JSObject JSObject::operator[] (int64 index) const
|
||||
{
|
||||
return getChild (index);
|
||||
}
|
||||
|
||||
bool JSObject::hasProperty (const Identifier& name) const
|
||||
{
|
||||
return impl->hasProperty (name);
|
||||
}
|
||||
|
||||
var JSObject::get() const
|
||||
{
|
||||
return impl->get();
|
||||
}
|
||||
|
||||
void JSObject::setProperty (const Identifier& name, const var& value) const
|
||||
{
|
||||
impl->setProperty (name, value);
|
||||
}
|
||||
|
||||
void JSObject::setProperty (int64 index, const var& value) const
|
||||
{
|
||||
impl->setProperty (index, value);
|
||||
}
|
||||
|
||||
var JSObject::invokeMethod (const Identifier& methodName,
|
||||
Span<const var> args,
|
||||
Result* result) const
|
||||
{
|
||||
const auto varOrError = impl->invokeMethod (methodName, args);
|
||||
|
||||
if (result != nullptr)
|
||||
{
|
||||
const auto* e = std::get_if<String> (&varOrError);
|
||||
*result = e != nullptr ? Result::fail (*e) : Result::ok();
|
||||
}
|
||||
|
||||
return discardError (varOrError);
|
||||
}
|
||||
|
||||
NamedValueSet JSObject::getProperties() const
|
||||
{
|
||||
return impl->getProperties();
|
||||
}
|
||||
|
||||
void JSObject::swap (JSObject& other) noexcept
|
||||
{
|
||||
std::swap (impl, other.impl);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
JSCursor::JSCursor (JSObject rootIn) : root (std::move (rootIn))
|
||||
{
|
||||
}
|
||||
|
||||
var JSCursor::get() const
|
||||
{
|
||||
if (const auto resolved = getFullResolution())
|
||||
return resolved->get();
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
void JSCursor::set (const var& value) const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
|
||||
if (! resolved.has_value())
|
||||
{
|
||||
jassertfalse; // Can't resolve an Object to change along the path stored in the cursor
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
|
||||
if (! property.has_value())
|
||||
{
|
||||
jassertfalse; // Can't set the value of the root Object
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* prop = std::get_if<Identifier> (&(*property)))
|
||||
{
|
||||
object.setProperty (*prop, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* prop = std::get_if<int64> (&(*property)))
|
||||
{
|
||||
object.setProperty (*prop, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JSCursor JSCursor::getChild (const Identifier& name) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.path.emplace_back (name);
|
||||
return copy;
|
||||
}
|
||||
|
||||
JSCursor JSCursor::operator[] (const Identifier& name) const
|
||||
{
|
||||
return getChild (name);
|
||||
}
|
||||
|
||||
JSCursor JSCursor::getChild (int64 index) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.path.emplace_back (index);
|
||||
return copy;
|
||||
}
|
||||
|
||||
JSCursor JSCursor::operator[] (int64 index) const
|
||||
{
|
||||
return getChild (index);
|
||||
}
|
||||
|
||||
JSObject JSCursor::getOrCreateObject() const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
jassert (resolved.has_value());
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
|
||||
if (! property.has_value())
|
||||
return object;
|
||||
|
||||
auto* integerValue = std::get_if<int64> (&(*property));
|
||||
|
||||
jassert (integerValue == nullptr
|
||||
|| (object.isArray() && (*integerValue) < object.getSize()));
|
||||
|
||||
if (integerValue != nullptr)
|
||||
return object[*integerValue];
|
||||
|
||||
auto* prop = std::get_if<Identifier> (&(*property));
|
||||
jassert(prop != nullptr);
|
||||
return object[*prop];
|
||||
}
|
||||
|
||||
bool JSCursor::isValid() const
|
||||
{
|
||||
return getPartialResolution().has_value();
|
||||
}
|
||||
|
||||
bool JSCursor::isArray() const
|
||||
{
|
||||
if (auto resolved = getFullResolution())
|
||||
return resolved->isArray();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var JSCursor::invoke (Span<const var> args, Result* result) const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
|
||||
if (! resolved.has_value())
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
if (! property.has_value())
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
return object.invokeMethod (*std::get_if<Identifier> (&(*property)), args, result);
|
||||
}
|
||||
|
||||
std::optional<JSObject> JSCursor::resolve (JSObject object, Property property)
|
||||
{
|
||||
if (auto* index = std::get_if<int64> (&property))
|
||||
{
|
||||
if (! object.isArray())
|
||||
return std::nullopt;
|
||||
|
||||
if (! (*index < object.getSize()))
|
||||
return std::nullopt;
|
||||
|
||||
return object[*index];
|
||||
}
|
||||
|
||||
if (auto* key = std::get_if<Identifier> (&property))
|
||||
{
|
||||
if (! object.hasProperty (*key))
|
||||
return std::nullopt;
|
||||
|
||||
return object[*key];
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<JSCursor::PartialResolution> JSCursor::getPartialResolution() const
|
||||
{
|
||||
auto object = root;
|
||||
|
||||
for (int i = 0, iEnd = (int) path.size() - 1; i < iEnd; ++i)
|
||||
{
|
||||
const auto& property = path[(size_t) i];
|
||||
auto objectOpt = resolve (object, property);
|
||||
|
||||
if (! objectOpt.has_value())
|
||||
return std::nullopt;
|
||||
|
||||
object = *objectOpt;
|
||||
}
|
||||
|
||||
return std::make_optional<PartialResolution> (std::move (object),
|
||||
path.empty() ? std::nullopt
|
||||
: std::make_optional (path.back()));
|
||||
}
|
||||
|
||||
std::optional<JSObject> JSCursor::getFullResolution() const
|
||||
{
|
||||
if (auto partiallyResolved = getPartialResolution())
|
||||
{
|
||||
if (! partiallyResolved->second.has_value())
|
||||
return partiallyResolved->first;
|
||||
|
||||
return resolve (partiallyResolved->first, *(partiallyResolved->second));
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
} // namespace juce::detail
|
||||
219
modules/juce_javascript/javascript/juce_JSCursor.cpp
Normal file
219
modules/juce_javascript/javascript/juce_JSCursor.cpp
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
JSCursor::JSCursor (JSObject rootIn) : root (std::move (rootIn))
|
||||
{
|
||||
}
|
||||
|
||||
var JSCursor::get() const
|
||||
{
|
||||
if (const auto resolved = getFullResolution())
|
||||
return resolved->get();
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
void JSCursor::set (const var& value) const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
|
||||
if (! resolved.has_value())
|
||||
{
|
||||
jassertfalse; // Can't resolve an Object to change along the path stored in the cursor
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
|
||||
if (! property.has_value())
|
||||
{
|
||||
jassertfalse; // Can't set the value of the root Object
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* prop = std::get_if<Identifier> (&(*property)))
|
||||
{
|
||||
object.setProperty (*prop, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* prop = std::get_if<int64> (&(*property)))
|
||||
{
|
||||
object.setProperty (*prop, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JSCursor JSCursor::getChild (const Identifier& name) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.path.emplace_back (name);
|
||||
return copy;
|
||||
}
|
||||
|
||||
JSCursor JSCursor::operator[] (const Identifier& name) const
|
||||
{
|
||||
return getChild (name);
|
||||
}
|
||||
|
||||
JSCursor JSCursor::getChild (int64 index) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.path.emplace_back (index);
|
||||
return copy;
|
||||
}
|
||||
|
||||
JSCursor JSCursor::operator[] (int64 index) const
|
||||
{
|
||||
return getChild (index);
|
||||
}
|
||||
|
||||
JSObject JSCursor::getOrCreateObject() const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
jassert (resolved.has_value());
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
|
||||
if (! property.has_value())
|
||||
return object;
|
||||
|
||||
auto* integerValue = std::get_if<int64> (&(*property));
|
||||
|
||||
jassert (integerValue == nullptr
|
||||
|| (object.isArray() && (*integerValue) < object.getSize()));
|
||||
|
||||
if (integerValue != nullptr)
|
||||
return object[*integerValue];
|
||||
|
||||
auto* prop = std::get_if<Identifier> (&(*property));
|
||||
jassert(prop != nullptr);
|
||||
return object[*prop];
|
||||
}
|
||||
|
||||
bool JSCursor::isValid() const
|
||||
{
|
||||
return getPartialResolution().has_value();
|
||||
}
|
||||
|
||||
bool JSCursor::isArray() const
|
||||
{
|
||||
if (auto resolved = getFullResolution())
|
||||
return resolved->isArray();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var JSCursor::invoke (Span<const var> args, Result* result) const
|
||||
{
|
||||
const auto resolved = getPartialResolution();
|
||||
|
||||
if (! resolved.has_value())
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto& [object, property] = *resolved;
|
||||
if (! property.has_value())
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
return object.invokeMethod (*std::get_if<Identifier> (&(*property)), args, result);
|
||||
}
|
||||
|
||||
std::optional<JSObject> JSCursor::resolve (JSObject object, Property property)
|
||||
{
|
||||
if (auto* index = std::get_if<int64> (&property))
|
||||
{
|
||||
if (! object.isArray())
|
||||
return std::nullopt;
|
||||
|
||||
if (! (*index < object.getSize()))
|
||||
return std::nullopt;
|
||||
|
||||
return object[*index];
|
||||
}
|
||||
|
||||
if (auto* key = std::get_if<Identifier> (&property))
|
||||
{
|
||||
if (! object.hasProperty (*key))
|
||||
return std::nullopt;
|
||||
|
||||
return object[*key];
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<JSCursor::PartialResolution> JSCursor::getPartialResolution() const
|
||||
{
|
||||
auto object = root;
|
||||
|
||||
for (int i = 0, iEnd = (int) path.size() - 1; i < iEnd; ++i)
|
||||
{
|
||||
const auto& property = path[(size_t) i];
|
||||
auto objectOpt = resolve (object, property);
|
||||
|
||||
if (! objectOpt.has_value())
|
||||
return std::nullopt;
|
||||
|
||||
object = *objectOpt;
|
||||
}
|
||||
|
||||
return std::make_optional<PartialResolution> (std::move (object),
|
||||
path.empty() ? std::nullopt
|
||||
: std::make_optional (path.back()));
|
||||
}
|
||||
|
||||
std::optional<JSObject> JSCursor::getFullResolution() const
|
||||
{
|
||||
if (auto partiallyResolved = getPartialResolution())
|
||||
{
|
||||
if (! partiallyResolved->second.has_value())
|
||||
return partiallyResolved->first;
|
||||
|
||||
return resolve (partiallyResolved->first, *(partiallyResolved->second));
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
193
modules/juce_javascript/javascript/juce_JSCursor.h
Normal file
193
modules/juce_javascript/javascript/juce_JSCursor.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
A high-level wrapper around an owning root JSObject and a hierarchical path relative to it.
|
||||
|
||||
It can be used to query and manipulate the location relative to the root JSObject in the
|
||||
Javascript Object graph. A cursor only maintains ownership of the root Object. So as long as a
|
||||
cursor points at the root it will always remain in a valid state, and isValid will return true.
|
||||
|
||||
Using getChild you can add elements to the cursor's relative path. You need to ensure that the
|
||||
cursor is in a valid state when calling get or set in such cases. You can use the isValid
|
||||
function to determine if the cursor currently points to a reachable location.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JSCursor
|
||||
{
|
||||
public:
|
||||
/** Creates a JSCursor that points to the provided root object and also participates in its
|
||||
ownership. This guarantees that this root object will remain valid for the lifetime of
|
||||
this cursor.
|
||||
|
||||
Child JSCursors created by getChild() will contain this same root object and each will
|
||||
further ensure that this root remains valid through reference counting.
|
||||
|
||||
While the validity of the root is ensured through shared ownership, the JSCursor itself is
|
||||
not guaranteed to be valid, unless its also pointing directly at the root.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
explicit JSCursor (JSObject root);
|
||||
|
||||
/** Returns an owning reference to the Javascript Object at the cursor's location. If there is
|
||||
no Object at the location but the cursor is valid, a new Object will be created.
|
||||
|
||||
You must only call this function on a valid JSCursor.
|
||||
|
||||
By creating an owning reference, you can create a new JSCursor object that owns the
|
||||
underlying object and is guaranteed to remain in a valid state e.g.
|
||||
|
||||
@code
|
||||
JSCursor rootCursor { engine.getRootObject() };
|
||||
auto nonOwningCursor = rootCursor["path"]["to"]["object"];
|
||||
|
||||
jassert (nonOwningCursor.isValid());
|
||||
|
||||
JSCursor owningCursor { nonOwningCursor.getOrCreateObject(); };
|
||||
engine.execute (arbitraryScript);
|
||||
|
||||
// owningCursor is guaranteed to remain valid even after subsequent script evaluations
|
||||
jassert (owningCursor.isValid());
|
||||
@endcode
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
JSObject getOrCreateObject() const;
|
||||
|
||||
/** Returns the value corresponding to the Object that the cursor points to. If there is no
|
||||
Object at the cursor's location var::undefined() is returned.
|
||||
|
||||
This function is safe to call for invalid cursors.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
var get() const;
|
||||
|
||||
/** Sets the Object under the cursor's location to the specified value.
|
||||
|
||||
You must only call this function for valid cursors.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
void set (const var& value) const;
|
||||
|
||||
/** Invokes this node as though it were a method. If the optional Result pointer is provided it
|
||||
will contain Result::ok() in case of success, or an error message in case an exception was
|
||||
thrown during evaluation.
|
||||
|
||||
You must only call this function for valid cursors.
|
||||
*/
|
||||
var invoke (Span<const var> args, Result* result = nullptr) const;
|
||||
|
||||
/** Equivalent to invoke(). */
|
||||
var operator() (Span<const var> args, Result* result = nullptr) const
|
||||
{
|
||||
return invoke (args, result);
|
||||
}
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
|
||||
appended to the cursor's location.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
*/
|
||||
JSCursor getChild (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
|
||||
appended to the cursor's location.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
Shorthand for getChild.
|
||||
*/
|
||||
JSCursor operator[] (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
|
||||
appended to the cursor's location. This overload will create a path that indexes into an
|
||||
Array.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
*/
|
||||
JSCursor getChild (int64 index) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
|
||||
appended to the cursor's location. This overload will create a path that indexes into an
|
||||
Array.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
Shorthand for getChild.
|
||||
*/
|
||||
JSCursor operator[] (int64 index) const;
|
||||
|
||||
/** Returns true if the location of the cursor is reachable from the cursor's JSObject root.
|
||||
This means it is safe to call set on this JSCursor and the location will then point to an
|
||||
Object corresponding to the supplied value.
|
||||
|
||||
It isn't guaranteed that there is already an Object at this location, in which case calling
|
||||
get will return var::undefined().
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/** Returns true if there is an Array under the cursor's location.
|
||||
|
||||
It is safe to call this function on an invalid cursor.
|
||||
*/
|
||||
bool isArray() const;
|
||||
|
||||
private:
|
||||
using Property = std::variant<Identifier, int64>;
|
||||
using PartialResolution = std::pair<JSObject, std::optional<Property>>;
|
||||
|
||||
static std::optional<JSObject> resolve (JSObject reference, Property property);
|
||||
|
||||
// Resolves the path to the second to last element. By taking ownership (creating an object for)
|
||||
// of the second to last element, the result of a successful partial resolution can be used to
|
||||
// construct the last element if it doesn't yet exist.
|
||||
std::optional<PartialResolution> getPartialResolution() const;
|
||||
|
||||
// Fully resolves the path and takes ownership of the object that was specified by it.
|
||||
std::optional<JSObject> getFullResolution() const;
|
||||
|
||||
JSObject root;
|
||||
std::vector<Property> path;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
284
modules/juce_javascript/javascript/juce_JSObject.cpp
Normal file
284
modules/juce_javascript/javascript/juce_JSObject.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wsubobject-linkage")
|
||||
class JSObject::Impl
|
||||
{
|
||||
public:
|
||||
using ValuePtr = detail::qjs::QuickJSContext::ValuePtr;
|
||||
|
||||
explicit Impl (const detail::QuickJSWrapper* engineIn)
|
||||
: Impl (engineIn,
|
||||
{ detail::qjs::JS_GetGlobalObject (engineIn->getQuickJSContext()), engineIn->getQuickJSContext() })
|
||||
{
|
||||
}
|
||||
|
||||
Impl (const Impl& other)
|
||||
: Impl (other.engine,
|
||||
{ detail::qjs::JS_DupValue (other.engine->getQuickJSContext(), other.valuePtr.get()),
|
||||
other.engine->getQuickJSContext() })
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Impl> getChild (const Identifier& prop) const
|
||||
{
|
||||
return rawToUniquePtr (new Impl (engine, { detail::getOrCreateProperty (engine->getQuickJSContext(),
|
||||
valuePtr.get(),
|
||||
prop.toString().toRawUTF8()),
|
||||
engine->getQuickJSContext() }));
|
||||
}
|
||||
|
||||
std::unique_ptr<Impl> getChild (int64 index) const
|
||||
{
|
||||
jassert (isArray());
|
||||
return rawToUniquePtr (new Impl (engine, valuePtr[detail::toUint32 (index)]));
|
||||
}
|
||||
|
||||
bool hasProperty (const Identifier& name) const
|
||||
{
|
||||
return detail::hasProperty (engine->getQuickJSContext(), valuePtr.get(), name.toString().toRawUTF8());
|
||||
}
|
||||
|
||||
void setProperty (const Identifier& name, const var& value) const
|
||||
{
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
|
||||
detail::qjs::JS_SetPropertyStr (ctx, valuePtr.get(), name.toString().toRawUTF8(), detail::juceToQuickJs (value, ctx));
|
||||
}
|
||||
|
||||
void setProperty (int64 index, const var& value) const
|
||||
{
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
|
||||
detail::qjs::JS_SetPropertyInt64 (ctx, valuePtr.get(), index, detail::juceToQuickJs (value, ctx));
|
||||
}
|
||||
|
||||
var get() const
|
||||
{
|
||||
if (auto* opaque = detail::qjs::JS_GetOpaque (valuePtr.get(), detail::DynamicObjectWrapper::getClassId()))
|
||||
if (detail::DynamicObjectWrapper::getDynamicObjects().count (opaque) != 0)
|
||||
return { static_cast<detail::DynamicObjectWrapper*> (opaque)->object.get() };
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
return detail::discardError (detail::quickJSToJuce ({ detail::qjs::JS_DupValue (ctx, valuePtr.get()), ctx }));
|
||||
}
|
||||
|
||||
detail::VarOrError invokeMethod (const Identifier& methodName, Span<const var> args) const
|
||||
{
|
||||
if (! hasProperty (methodName))
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
const auto methodAtom = JS_NewAtom (ctx, methodName.toString().toRawUTF8());
|
||||
ScopeGuard scope { [&] { detail::qjs::JS_FreeAtom (ctx, methodAtom); } };
|
||||
|
||||
detail::JSFunctionArguments arguments { ctx, args };
|
||||
|
||||
ValuePtr returnVal { detail::qjs::JS_Invoke (ctx,
|
||||
valuePtr.get(),
|
||||
methodAtom,
|
||||
arguments.getSize(),
|
||||
arguments.getArguments()),
|
||||
ctx };
|
||||
|
||||
return detail::quickJSToJuce (returnVal);
|
||||
}
|
||||
|
||||
NamedValueSet getProperties() const
|
||||
{
|
||||
NamedValueSet result;
|
||||
|
||||
auto* ctx = engine->getQuickJSContext();
|
||||
ValuePtr names { detail::qjs::JS_GetOwnPropertyNames2 (ctx,
|
||||
valuePtr.get(),
|
||||
detail::qjs::JS_GPN_ENUM_ONLY | detail::qjs::JS_GPN_STRING_MASK,
|
||||
detail::qjs::JS_ITERATOR_KIND_KEY),
|
||||
ctx };
|
||||
|
||||
|
||||
if (auto v = detail::discardError (detail::quickJSToJuce (names)); const auto* propertyNames = v.getArray())
|
||||
{
|
||||
for (const auto& name : *propertyNames)
|
||||
{
|
||||
if (name.isString())
|
||||
{
|
||||
const Identifier prop { name.toString() };
|
||||
result.set (prop, getChild (prop)->get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return detail::qjs::JS_IsArray (engine->getQuickJSContext(), valuePtr.get());
|
||||
}
|
||||
|
||||
int64 getSize() const
|
||||
{
|
||||
if (! isArray())
|
||||
{
|
||||
jassertfalse;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto lengthProp = valuePtr["length"];
|
||||
uint32_t length = 0;
|
||||
detail::qjs::JS_ToUint32 (engine->getQuickJSContext(), &length, lengthProp.get());
|
||||
return (int64) length;
|
||||
}
|
||||
|
||||
private:
|
||||
Impl (const detail::QuickJSWrapper* e, ValuePtr&& ptr)
|
||||
: engine (e), valuePtr (std::move (ptr))
|
||||
{
|
||||
}
|
||||
|
||||
const detail::QuickJSWrapper* engine = nullptr;
|
||||
ValuePtr valuePtr;
|
||||
};
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
JSObject::JSObject (const detail::QuickJSWrapper* engine)
|
||||
: impl (new Impl (engine))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::JSObject (std::unique_ptr<Impl> implIn)
|
||||
: impl (std::move (implIn))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::JSObject (const JSObject& other)
|
||||
: impl (new Impl (*other.impl))
|
||||
{
|
||||
}
|
||||
|
||||
JSObject::~JSObject() = default;
|
||||
|
||||
JSObject::JSObject (JSObject&&) noexcept = default;
|
||||
|
||||
JSObject& JSObject::operator= (const JSObject& other)
|
||||
{
|
||||
JSObject { other }.swap (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSObject& JSObject::operator= (JSObject&& other) noexcept = default;
|
||||
|
||||
JSObject JSObject::getChild (const Identifier& name) const
|
||||
{
|
||||
return JSObject { impl->getChild (name) };
|
||||
}
|
||||
|
||||
JSObject JSObject::operator[] (const Identifier& name) const
|
||||
{
|
||||
return getChild (name);
|
||||
}
|
||||
|
||||
bool JSObject::isArray() const
|
||||
{
|
||||
return impl->isArray();
|
||||
}
|
||||
|
||||
int64 JSObject::getSize() const
|
||||
{
|
||||
return impl->getSize();
|
||||
}
|
||||
|
||||
JSObject JSObject::getChild (int64 index) const
|
||||
{
|
||||
jassert (isArray());
|
||||
return JSObject { impl->getChild (index) };
|
||||
}
|
||||
|
||||
JSObject JSObject::operator[] (int64 index) const
|
||||
{
|
||||
return getChild (index);
|
||||
}
|
||||
|
||||
bool JSObject::hasProperty (const Identifier& name) const
|
||||
{
|
||||
return impl->hasProperty (name);
|
||||
}
|
||||
|
||||
var JSObject::get() const
|
||||
{
|
||||
return impl->get();
|
||||
}
|
||||
|
||||
void JSObject::setProperty (const Identifier& name, const var& value) const
|
||||
{
|
||||
impl->setProperty (name, value);
|
||||
}
|
||||
|
||||
void JSObject::setProperty (int64 index, const var& value) const
|
||||
{
|
||||
impl->setProperty (index, value);
|
||||
}
|
||||
|
||||
var JSObject::invokeMethod (const Identifier& methodName,
|
||||
Span<const var> args,
|
||||
Result* result) const
|
||||
{
|
||||
const auto varOrError = impl->invokeMethod (methodName, args);
|
||||
|
||||
if (result != nullptr)
|
||||
{
|
||||
const auto* e = std::get_if<String> (&varOrError);
|
||||
*result = e != nullptr ? Result::fail (*e) : Result::ok();
|
||||
}
|
||||
|
||||
return detail::discardError (varOrError);
|
||||
}
|
||||
|
||||
NamedValueSet JSObject::getProperties() const
|
||||
{
|
||||
return impl->getProperties();
|
||||
}
|
||||
|
||||
void JSObject::swap (JSObject& other) noexcept
|
||||
{
|
||||
std::swap (impl, other.impl);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
168
modules/juce_javascript/javascript/juce_JSObject.h
Normal file
168
modules/juce_javascript/javascript/juce_JSObject.h
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
A JSObject represents an owning reference to the underlying JS object, meaning it will remain
|
||||
valid even if a subsequent script execution deletes other handles to it.
|
||||
|
||||
Objects of this class can be used to traverse the current object graph inside the specified
|
||||
Javascript engine.
|
||||
|
||||
This is a low-level providing only operations that map directly to the underlying Javascript
|
||||
Object implementation. The JSCursor class generally provides a more convenient interface with
|
||||
functions that may fail based on the Javascript engine's current state.
|
||||
|
||||
@see JSCursor
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JSObject
|
||||
{
|
||||
public:
|
||||
/** Constructor, used internally by the JavascriptEngine implementation.
|
||||
|
||||
To create a new JSObject pointing at the root object of the engine's context use
|
||||
JavascriptEngine::getRootObject().
|
||||
*/
|
||||
explicit JSObject (const detail::QuickJSWrapper* engine);
|
||||
|
||||
/** Destructor. */
|
||||
~JSObject();
|
||||
|
||||
/** Copy constructor. */
|
||||
JSObject (const JSObject&);
|
||||
|
||||
/** Move constructor. */
|
||||
JSObject (JSObject&&) noexcept;
|
||||
|
||||
/** Copy assignment operator. */
|
||||
JSObject& operator= (const JSObject&);
|
||||
|
||||
/** Move assignment operator. */
|
||||
JSObject& operator= (JSObject&&) noexcept;
|
||||
|
||||
/** Returns a new cursor pointing to a JS object that is a property of the parent cursor's
|
||||
underlying object and has the provided name.
|
||||
|
||||
You can use hasProperty() to check if such a property exists prior to the creation of this
|
||||
cursor. If no such property exists, this constructor will create a new JS Object and attach
|
||||
it to the parent under the specified name. This can be used to manipulate the object graph.
|
||||
*/
|
||||
JSObject getChild (const Identifier& name) const;
|
||||
|
||||
/** Returns a cursor object pointing to the property with the given name. If such property
|
||||
doesn't exist it will be created as an empty JS Object. Shorthand for getChild.
|
||||
*/
|
||||
JSObject operator[] (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor object pointing to the specified element in an Array.
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
JSObject getChild (int64 index) const;
|
||||
|
||||
/** Returns a new cursor object pointing to the specified element in an Array. This function is
|
||||
a shorthand for getChild (int64).
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
JSObject operator[] (int64 index) const;
|
||||
|
||||
/** Returns true if the JS Object under the cursor is an Array.
|
||||
|
||||
You can use getChild() or operator[]() to get a cursor to individual elements in the
|
||||
array or get() to obtain a JUCE variant wrapping all array elements.
|
||||
*/
|
||||
bool isArray() const;
|
||||
|
||||
/** Returns the size of the underlying JS Array.
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
int64 getSize() const;
|
||||
|
||||
/** Returns true if the object under the cursor has a property with the given name. */
|
||||
bool hasProperty (const Identifier& name) const;
|
||||
|
||||
/** Returns a variant with a value of the property under the given name. If no such property
|
||||
exists an undefined variant is returned.
|
||||
|
||||
If this property points to an object created by JavascriptEngine::registerNativeObject(),
|
||||
then the returned variant will contain a pointer to the original object and can be acquired
|
||||
by variant::getDynamicObject().
|
||||
*/
|
||||
var get() const;
|
||||
|
||||
/** Adds a named property to the underlying Object with the provided value, or assigns this
|
||||
value to an existing property with this name.
|
||||
*/
|
||||
void setProperty (const Identifier& name, const var& value) const;
|
||||
|
||||
/** Adds a property with an integral identifier and the provided value to the underlying Object,
|
||||
or assigns the value to an existing property.
|
||||
|
||||
If the underlying Object is also an Array, then the provided value will be assigned to the
|
||||
specified element of this Array, and ensure that it will have a size of at least index - 1.
|
||||
*/
|
||||
void setProperty (int64 index, const var& value) const;
|
||||
|
||||
/** Invokes this node as though it were a method.
|
||||
|
||||
If the optional Result pointer is provided it will contain Result::ok() in case of success,
|
||||
or an error message in case an exception was thrown during evaluation.
|
||||
*/
|
||||
var invokeMethod (const Identifier& methodName, Span<const var> args, Result* result = nullptr) const;
|
||||
|
||||
/** Returns all properties of the current object that are own properties, i.e. not inherited. */
|
||||
NamedValueSet getProperties() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
explicit JSObject (std::unique_ptr<Impl> implIn);
|
||||
|
||||
void swap (JSObject& other) noexcept;
|
||||
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -1,414 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
A JSObject represents an owning reference to the underlying JS object, meaning it will remain
|
||||
valid even if a subsequent script execution deletes other handles to it.
|
||||
|
||||
Objects of this class can be used to traverse the current object graph inside the specified
|
||||
Javascript engine.
|
||||
|
||||
This is a low-level providing only operations that map directly to the underlying Javascript
|
||||
Object implementation. The JSCursor class generally provides a more convenient interface with
|
||||
functions that may fail based on the Javascript engine's current state.
|
||||
|
||||
@see JSCursor
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JSObject
|
||||
{
|
||||
public:
|
||||
/** Constructor, used internally by the JavascriptEngine implementation.
|
||||
|
||||
To create a new JSObject pointing at the root object of the engine's context use
|
||||
JavascriptEngine::getRootObject().
|
||||
*/
|
||||
explicit JSObject (const detail::QuickJSWrapper* engine);
|
||||
|
||||
/** Destructor. */
|
||||
~JSObject();
|
||||
|
||||
/** Copy constructor. */
|
||||
JSObject (const JSObject&);
|
||||
|
||||
/** Move constructor. */
|
||||
JSObject (JSObject&&) noexcept;
|
||||
|
||||
/** Copy assignment operator. */
|
||||
JSObject& operator= (const JSObject&);
|
||||
|
||||
/** Move assignment operator. */
|
||||
JSObject& operator= (JSObject&&) noexcept;
|
||||
|
||||
/** Returns a new cursor pointing to a JS object that is a property of the parent cursor's
|
||||
underlying object and has the provided name.
|
||||
|
||||
You can use hasProperty() to check if such a property exists prior to the creation of this
|
||||
cursor. If no such property exists, this constructor will create a new JS Object and attach
|
||||
it to the parent under the specified name. This can be used to manipulate the object graph.
|
||||
*/
|
||||
JSObject getChild (const Identifier& name) const;
|
||||
|
||||
/** Returns a cursor object pointing to the property with the given name. If such property
|
||||
doesn't exist it will be created as an empty JS Object. Shorthand for getChild.
|
||||
*/
|
||||
JSObject operator[] (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor object pointing to the specified element in an Array.
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
JSObject getChild (int64 index) const;
|
||||
|
||||
/** Returns a new cursor object pointing to the specified element in an Array. This function is
|
||||
a shorthand for getChild (int64).
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
JSObject operator[] (int64 index) const;
|
||||
|
||||
/** Returns true if the JS Object under the cursor is an Array.
|
||||
|
||||
You can use getChild() or operator[]() to get a cursor to individual elements in the
|
||||
array or get() to obtain a JUCE variant wrapping all array elements.
|
||||
*/
|
||||
bool isArray() const;
|
||||
|
||||
/** Returns the size of the underlying JS Array.
|
||||
|
||||
You must ensure that the cursor points to an Array before calling this function.
|
||||
|
||||
@see isArray
|
||||
*/
|
||||
int64 getSize() const;
|
||||
|
||||
/** Returns true if the object under the cursor has a property with the given name. */
|
||||
bool hasProperty (const Identifier& name) const;
|
||||
|
||||
/** Returns a variant with a value of the property under the given name. If no such property
|
||||
exists an undefined variant is returned.
|
||||
|
||||
If this property points to an object created by JavascriptEngine::registerNativeObject(),
|
||||
then the returned variant will contain a pointer to the original object and can be acquired
|
||||
by variant::getDynamicObject().
|
||||
*/
|
||||
var get() const;
|
||||
|
||||
/** Adds a named property to the underlying Object with the provided value, or assigns this
|
||||
value to an existing property with this name.
|
||||
*/
|
||||
void setProperty (const Identifier& name, const var& value) const;
|
||||
|
||||
/** Adds a property with an integral identifier and the provided value to the underlying Object,
|
||||
or assigns the value to an existing property.
|
||||
|
||||
If the underlying Object is also an Array, then the provided value will be assigned to the
|
||||
specified element of this Array, and ensure that it will have a size of at least index - 1.
|
||||
*/
|
||||
void setProperty (int64 index, const var& value) const;
|
||||
|
||||
/** Invokes this node as though it were a method.
|
||||
|
||||
If the optional Result pointer is provided it will contain Result::ok() in case of success,
|
||||
or an error message in case an exception was thrown during evaluation.
|
||||
*/
|
||||
var invokeMethod (const Identifier& methodName, Span<const var> args, Result* result = nullptr) const;
|
||||
|
||||
/** Returns all properties of the current object that are own properties, i.e. not inherited. */
|
||||
NamedValueSet getProperties() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
explicit JSObject (std::unique_ptr<Impl> implIn);
|
||||
|
||||
void swap (JSObject& other) noexcept;
|
||||
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
/**
|
||||
A high-level wrapper around an owning root JSObject and a hierarchical path relative to it.
|
||||
|
||||
It can be used to query and manipulate the location relative to the root JSObject in the
|
||||
Javascript Object graph. A cursor only maintains ownership of the root Object. So as long as a
|
||||
cursor points at the root it will always remain in a valid state, and isValid will return true.
|
||||
|
||||
Using getChild you can add elements to the cursor's relative path. You need to ensure that the
|
||||
cursor is in a valid state when calling get or set in such cases. You can use the isValid
|
||||
function to determine if the cursor currently points to a reachable location.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JSCursor
|
||||
{
|
||||
public:
|
||||
/** Creates a JSCursor that points to the provided root object and also participates in its
|
||||
ownership. This guarantees that this root object will remain valid for the lifetime of
|
||||
this cursor.
|
||||
|
||||
Child JSCursors created by getChild() will contain this same root object and each will
|
||||
further ensure that this root remains valid through reference counting.
|
||||
|
||||
While the validity of the root is ensured through shared ownership, the JSCursor itself is
|
||||
not guaranteed to be valid, unless its also pointing directly at the root.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
explicit JSCursor (JSObject root);
|
||||
|
||||
/** Returns an owning reference to the Javascript Object at the cursor's location. If there is
|
||||
no Object at the location but the cursor is valid, a new Object will be created.
|
||||
|
||||
You must only call this function on a valid JSCursor.
|
||||
|
||||
By creating an owning reference, you can create a new JSCursor object that owns the
|
||||
underlying object and is guaranteed to remain in a valid state e.g.
|
||||
|
||||
@code
|
||||
JSCursor rootCursor { engine.getRootObject() };
|
||||
auto nonOwningCursor = rootCursor["path"]["to"]["object"];
|
||||
|
||||
jassert (nonOwningCursor.isValid());
|
||||
|
||||
JSCursor owningCursor { nonOwningCursor.getOrCreateObject(); };
|
||||
engine.execute (arbitraryScript);
|
||||
|
||||
// owningCursor is guaranteed to remain valid even after subsequent script evaluations
|
||||
jassert (owningCursor.isValid());
|
||||
@endcode
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
JSObject getOrCreateObject() const;
|
||||
|
||||
/** Returns the value corresponding to the Object that the cursor points to. If there is no
|
||||
Object at the cursor's location var::undefined() is returned.
|
||||
|
||||
This function is safe to call for invalid cursors.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
var get() const;
|
||||
|
||||
/** Sets the Object under the cursor's location to the specified value.
|
||||
|
||||
You must only call this function for valid cursors.
|
||||
|
||||
@see isValid
|
||||
*/
|
||||
void set (const var& value) const;
|
||||
|
||||
/** Invokes this node as though it were a method. If the optional Result pointer is provided it
|
||||
will contain Result::ok() in case of success, or an error message in case an exception was
|
||||
thrown during evaluation.
|
||||
|
||||
You must only call this function for valid cursors.
|
||||
*/
|
||||
var invoke (Span<const var> args, Result* result = nullptr) const;
|
||||
|
||||
/** Equivalent to invoke(). */
|
||||
var operator() (Span<const var> args, Result* result = nullptr) const
|
||||
{
|
||||
return invoke (args, result);
|
||||
}
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
|
||||
appended to the cursor's location.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
*/
|
||||
JSCursor getChild (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the name parameter
|
||||
appended to the cursor's location.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
Shorthand for getChild.
|
||||
*/
|
||||
JSCursor operator[] (const Identifier& name) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
|
||||
appended to the cursor's location. This overload will create a path that indexes into an
|
||||
Array.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
*/
|
||||
JSCursor getChild (int64 index) const;
|
||||
|
||||
/** Returns a new cursor that has the same root Object as the parent and has the index parameter
|
||||
appended to the cursor's location. This overload will create a path that indexes into an
|
||||
Array.
|
||||
|
||||
If the new path points to a location unreachable from the root, the resulting JSCursor
|
||||
object will be invalid. This however can change due to subsequent script executions.
|
||||
Shorthand for getChild.
|
||||
*/
|
||||
JSCursor operator[] (int64 index) const;
|
||||
|
||||
/** Returns true if the location of the cursor is reachable from the cursor's JSObject root.
|
||||
This means it is safe to call set on this JSCursor and the location will then point to an
|
||||
Object corresponding to the supplied value.
|
||||
|
||||
It isn't guaranteed that there is already an Object at this location, in which case calling
|
||||
get will return var::undefined().
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/** Returns true if there is an Array under the cursor's location.
|
||||
|
||||
It is safe to call this function on an invalid cursor.
|
||||
*/
|
||||
bool isArray() const;
|
||||
|
||||
private:
|
||||
using Property = std::variant<Identifier, int64>;
|
||||
using PartialResolution = std::pair<JSObject, std::optional<Property>>;
|
||||
|
||||
static std::optional<JSObject> resolve (JSObject reference, Property property);
|
||||
|
||||
// Resolves the path to the second to last element. By taking ownership (creating an object for)
|
||||
// of the second to last element, the result of a successful partial resolution can be used to
|
||||
// construct the last element if it doesn't yet exist.
|
||||
std::optional<PartialResolution> getPartialResolution() const;
|
||||
|
||||
// Fully resolves the path and takes ownership of the object that was specified by it.
|
||||
std::optional<JSObject> getFullResolution() const;
|
||||
|
||||
JSObject root;
|
||||
std::vector<Property> path;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A simple javascript interpreter!
|
||||
|
||||
It's not fully standards-compliant, and won't be as fast as the fancy JIT-compiled
|
||||
engines that you get in browsers, but this is an extremely compact, low-overhead javascript
|
||||
interpreter, which is integrated with the juce var and DynamicObject classes. If you need
|
||||
a few simple bits of scripting in your app, and want to be able to easily let the JS
|
||||
work with native objects defined as DynamicObject subclasses, then this might do the job.
|
||||
|
||||
To use, simply create an instance of this class and call execute() to run your code.
|
||||
Variables that the script sets can be retrieved with evaluate(), and if you need to provide
|
||||
native objects for the script to use, you can add them with registerNativeObject().
|
||||
|
||||
One caveat: Because the values and objects that the engine works with are DynamicObject
|
||||
and var objects, they use reference-counting rather than garbage-collection, so if your
|
||||
script creates complex connections between objects, you run the risk of creating cyclic
|
||||
dependencies and hence leaking.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JavascriptEngine final
|
||||
{
|
||||
public:
|
||||
/** Creates an instance of the engine.
|
||||
*/
|
||||
JavascriptEngine();
|
||||
|
||||
/** Destructor. */
|
||||
~JavascriptEngine();
|
||||
|
||||
/** Attempts to parse and run a block of javascript code.
|
||||
If there's a parse or execution error, the error description is returned in
|
||||
the result.
|
||||
You can specify a maximum time for which the program is allowed to run, and
|
||||
it'll return with an error message if this time is exceeded.
|
||||
*/
|
||||
Result execute (const String& javascriptCode);
|
||||
|
||||
/** Attempts to parse and run a javascript expression, and returns the result.
|
||||
If there's a syntax error, or the expression can't be evaluated, the return value
|
||||
will be var::undefined(). The errorMessage parameter gives you a way to find out
|
||||
any parsing errors.
|
||||
If the expression is successfully evaluated but yields no result the return value
|
||||
will be a void var.
|
||||
You can specify a maximum time for which the program is allowed to run, and
|
||||
it'll return with an error message if this time is exceeded.
|
||||
*/
|
||||
var evaluate (const String& javascriptCode,
|
||||
Result* errorMessage = nullptr);
|
||||
|
||||
/** Calls a function in the root namespace, and returns the result.
|
||||
The function arguments are passed in the same format as used by native
|
||||
methods in the var class.
|
||||
*/
|
||||
var callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage = nullptr);
|
||||
|
||||
/** Adds a native object to the root namespace.
|
||||
The object passed-in is reference-counted, and will be retained by the
|
||||
engine until the engine is deleted. The name must be a simple JS identifier,
|
||||
without any dots.
|
||||
*/
|
||||
void registerNativeObject (const Identifier& objectName, DynamicObject* object);
|
||||
|
||||
/** This value indicates how long a call to one of the evaluate methods is permitted
|
||||
to run before timing-out and failing.
|
||||
The default value is a number of seconds, but you can change this to whatever value
|
||||
suits your application.
|
||||
*/
|
||||
RelativeTime maximumExecutionTime;
|
||||
|
||||
/** When called from another thread, causes the interpreter to time-out as soon as possible */
|
||||
void stop() noexcept;
|
||||
|
||||
/** Returns the object from which all Javascript objects are reachable in the engine's context.
|
||||
*/
|
||||
JSObject getRootObject() const;
|
||||
|
||||
/** Provides access to the set of properties of the root namespace object. */
|
||||
NamedValueSet getRootObjectProperties() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine)
|
||||
JUCE_DECLARE_NON_MOVEABLE (JavascriptEngine)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
247
modules/juce_javascript/javascript/juce_JavascriptEngine.cpp
Normal file
247
modules/juce_javascript/javascript/juce_JavascriptEngine.cpp
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class JavascriptEngine::Impl
|
||||
{
|
||||
public:
|
||||
using ValuePtr = detail::qjs::QuickJSContext::ValuePtr;
|
||||
|
||||
//==============================================================================
|
||||
Impl()
|
||||
{
|
||||
detail::DynamicObjectWrapper::createClass (engine.getQuickJSRuntime());
|
||||
|
||||
engine.setInterruptHandler ([this]
|
||||
{
|
||||
return (int64) Time::getMillisecondCounterHiRes() >= timeout;
|
||||
});
|
||||
}
|
||||
|
||||
void registerNativeObject (const Identifier& name,
|
||||
DynamicObject::Ptr dynamicObject,
|
||||
std::optional<detail::qjs::JSValue> parent = std::nullopt)
|
||||
{
|
||||
auto wrapper = std::make_unique<detail::DynamicObjectWrapper> (engine, dynamicObject);
|
||||
auto* ctx = engine.getQuickJSContext();
|
||||
auto jsObject = JS_NewObjectClass (ctx, (int) detail::DynamicObjectWrapper::getClassId());
|
||||
detail::qjs::JS_SetOpaque (jsObject, (void*) wrapper.get());
|
||||
|
||||
std::vector<detail::qjs::JSCFunctionListEntry> propertyFunctionList;
|
||||
|
||||
for (const auto& [identifier, prop] : wrapper->getProperties())
|
||||
{
|
||||
auto* jsIdentifier = identifier.toString().toRawUTF8();
|
||||
|
||||
if (prop.isMethod())
|
||||
{
|
||||
detail::qjs::JS_SetPropertyStr (ctx,
|
||||
jsObject,
|
||||
jsIdentifier,
|
||||
JS_NewCFunctionMagic (ctx,
|
||||
detail::DynamicObjectWrapper::callDispatcher,
|
||||
jsIdentifier,
|
||||
0,
|
||||
detail::qjs::JS_CFUNC_generic_magic,
|
||||
wrapper->getOrdinal (identifier)));
|
||||
}
|
||||
else if (prop.isObject())
|
||||
{
|
||||
if (auto* embeddedObject = prop.getDynamicObject())
|
||||
registerNativeObject (identifier, embeddedObject, jsObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto entry = detail::makeFunctionListEntry (jsIdentifier,
|
||||
detail::DynamicObjectWrapper::getDispatcher,
|
||||
detail::DynamicObjectWrapper::setDispatcher,
|
||||
wrapper->getOrdinal (identifier));
|
||||
propertyFunctionList.push_back (entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (! propertyFunctionList.empty())
|
||||
{
|
||||
detail::qjs::JS_SetPropertyFunctionList (ctx,
|
||||
jsObject,
|
||||
propertyFunctionList.data(),
|
||||
(int) propertyFunctionList.size());
|
||||
}
|
||||
|
||||
const auto jsObjectName = name.toString().toRawUTF8();
|
||||
|
||||
if (parent.has_value())
|
||||
{
|
||||
detail::qjs::JS_SetPropertyStr (ctx, *parent, jsObjectName, jsObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
ValuePtr globalObject { detail::qjs::JS_GetGlobalObject (ctx), ctx };
|
||||
detail::qjs::JS_SetPropertyStr (ctx, globalObject.get(), jsObjectName, jsObject);
|
||||
}
|
||||
|
||||
wrapper.release();
|
||||
}
|
||||
|
||||
var evaluate (const String& code, Result* errorMessage, RelativeTime maxExecTime)
|
||||
{
|
||||
resetTimeout (maxExecTime);
|
||||
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::ok();
|
||||
|
||||
const auto result = detail::quickJSToJuce ({ JS_Eval (engine.getQuickJSContext(), code.toRawUTF8(), code.getNumBytesAsUTF8(), "", JS_EVAL_TYPE_GLOBAL), engine.getQuickJSContext() });
|
||||
|
||||
if (auto* v = std::get_if<var> (&result))
|
||||
return *v;
|
||||
|
||||
if (auto* e = std::get_if<String> (&result))
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::fail (*e);
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
Result execute (const String& code, RelativeTime maxExecTime)
|
||||
{
|
||||
auto result = Result::ok();
|
||||
evaluate (code, &result, maxExecTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
var callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage,
|
||||
RelativeTime maxExecTime)
|
||||
{
|
||||
resetTimeout (maxExecTime);
|
||||
|
||||
auto* ctx = engine.getQuickJSContext();
|
||||
const auto functionStr = function.toString();
|
||||
|
||||
const auto fn = detail::qjs::JS_NewAtomLen (ctx, functionStr.toRawUTF8(), functionStr.getNumBytesAsUTF8());
|
||||
|
||||
detail::JSFunctionArguments argList { ctx, args };
|
||||
|
||||
detail::qjs::QuickJSContext::ValuePtr global { JS_GetGlobalObject (ctx), ctx };
|
||||
detail::qjs::QuickJSContext::ValuePtr returnVal { JS_Invoke (ctx, global.get(), fn, argList.getSize(), argList.getArguments()), ctx };
|
||||
|
||||
JS_FreeAtom (ctx, fn);
|
||||
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::ok();
|
||||
|
||||
const auto result = detail::quickJSToJuce (returnVal);
|
||||
|
||||
if (auto* v = std::get_if<var> (&result))
|
||||
return *v;
|
||||
|
||||
if (auto* e = std::get_if<String> (&result))
|
||||
if (errorMessage != nullptr)
|
||||
*errorMessage = Result::fail (*e);
|
||||
|
||||
return var::undefined();
|
||||
}
|
||||
|
||||
void stop() noexcept
|
||||
{
|
||||
timeout = (int64) Time::getMillisecondCounterHiRes();
|
||||
}
|
||||
|
||||
JSObject getRootObject() const
|
||||
{
|
||||
return JSObject { &engine };
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void resetTimeout (RelativeTime maxExecTime)
|
||||
{
|
||||
timeout = (int64) Time::getMillisecondCounterHiRes() + maxExecTime.inMilliseconds();
|
||||
}
|
||||
|
||||
detail::QuickJSWrapper engine;
|
||||
std::atomic<int64> timeout{};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
JavascriptEngine::JavascriptEngine()
|
||||
: maximumExecutionTime (15.0),
|
||||
impl (std::make_unique<Impl>())
|
||||
{
|
||||
}
|
||||
|
||||
JavascriptEngine::~JavascriptEngine() = default;
|
||||
|
||||
void JavascriptEngine::registerNativeObject (const Identifier& name, DynamicObject* object)
|
||||
{
|
||||
impl->registerNativeObject (name, object);
|
||||
}
|
||||
|
||||
Result JavascriptEngine::execute (const String& javascriptCode)
|
||||
{
|
||||
return impl->execute (javascriptCode, maximumExecutionTime);
|
||||
}
|
||||
|
||||
var JavascriptEngine::evaluate (const String& javascriptCode, Result* errorMessage)
|
||||
{
|
||||
return impl->evaluate (javascriptCode, errorMessage, maximumExecutionTime);
|
||||
}
|
||||
|
||||
var JavascriptEngine::callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage)
|
||||
{
|
||||
return impl->callFunction (function, args, errorMessage, maximumExecutionTime);
|
||||
}
|
||||
|
||||
void JavascriptEngine::stop() noexcept
|
||||
{
|
||||
impl->stop();
|
||||
}
|
||||
|
||||
JSObject JavascriptEngine::getRootObject() const
|
||||
{
|
||||
return impl->getRootObject();
|
||||
}
|
||||
|
||||
NamedValueSet JavascriptEngine::getRootObjectProperties() const
|
||||
{
|
||||
return getRootObject().getProperties();
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
128
modules/juce_javascript/javascript/juce_JavascriptEngine.h
Normal file
128
modules/juce_javascript/javascript/juce_JavascriptEngine.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
A simple javascript interpreter!
|
||||
|
||||
It's not fully standards-compliant, and won't be as fast as the fancy JIT-compiled
|
||||
engines that you get in browsers, but this is an extremely compact, low-overhead javascript
|
||||
interpreter, which is integrated with the juce var and DynamicObject classes. If you need
|
||||
a few simple bits of scripting in your app, and want to be able to easily let the JS
|
||||
work with native objects defined as DynamicObject subclasses, then this might do the job.
|
||||
|
||||
To use, simply create an instance of this class and call execute() to run your code.
|
||||
Variables that the script sets can be retrieved with evaluate(), and if you need to provide
|
||||
native objects for the script to use, you can add them with registerNativeObject().
|
||||
|
||||
One caveat: Because the values and objects that the engine works with are DynamicObject
|
||||
and var objects, they use reference-counting rather than garbage-collection, so if your
|
||||
script creates complex connections between objects, you run the risk of creating cyclic
|
||||
dependencies and hence leaking.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API JavascriptEngine final
|
||||
{
|
||||
public:
|
||||
/** Creates an instance of the engine.
|
||||
*/
|
||||
JavascriptEngine();
|
||||
|
||||
/** Destructor. */
|
||||
~JavascriptEngine();
|
||||
|
||||
/** Attempts to parse and run a block of javascript code.
|
||||
If there's a parse or execution error, the error description is returned in
|
||||
the result.
|
||||
You can specify a maximum time for which the program is allowed to run, and
|
||||
it'll return with an error message if this time is exceeded.
|
||||
*/
|
||||
Result execute (const String& javascriptCode);
|
||||
|
||||
/** Attempts to parse and run a javascript expression, and returns the result.
|
||||
If there's a syntax error, or the expression can't be evaluated, the return value
|
||||
will be var::undefined(). The errorMessage parameter gives you a way to find out
|
||||
any parsing errors.
|
||||
If the expression is successfully evaluated but yields no result the return value
|
||||
will be a void var.
|
||||
You can specify a maximum time for which the program is allowed to run, and
|
||||
it'll return with an error message if this time is exceeded.
|
||||
*/
|
||||
var evaluate (const String& javascriptCode,
|
||||
Result* errorMessage = nullptr);
|
||||
|
||||
/** Calls a function in the root namespace, and returns the result.
|
||||
The function arguments are passed in the same format as used by native
|
||||
methods in the var class.
|
||||
*/
|
||||
var callFunction (const Identifier& function,
|
||||
const var::NativeFunctionArgs& args,
|
||||
Result* errorMessage = nullptr);
|
||||
|
||||
/** Adds a native object to the root namespace.
|
||||
The object passed-in is reference-counted, and will be retained by the
|
||||
engine until the engine is deleted. The name must be a simple JS identifier,
|
||||
without any dots.
|
||||
*/
|
||||
void registerNativeObject (const Identifier& objectName, DynamicObject* object);
|
||||
|
||||
/** This value indicates how long a call to one of the evaluate methods is permitted
|
||||
to run before timing-out and failing.
|
||||
The default value is a number of seconds, but you can change this to whatever value
|
||||
suits your application.
|
||||
*/
|
||||
RelativeTime maximumExecutionTime;
|
||||
|
||||
/** When called from another thread, causes the interpreter to time-out as soon as possible */
|
||||
void stop() noexcept;
|
||||
|
||||
/** Returns the object from which all Javascript objects are reachable in the engine's context.
|
||||
*/
|
||||
JSObject getRootObject() const;
|
||||
|
||||
/** Provides access to the set of properties of the root namespace object. */
|
||||
NamedValueSet getRootObjectProperties() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine)
|
||||
JUCE_DECLARE_NON_MOVEABLE (JavascriptEngine)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -52,7 +52,11 @@
|
|||
#include <juce_javascript/choc/javascript/choc_javascript_QuickJS.h>
|
||||
#undef choc
|
||||
|
||||
#include "javascript/juce_Javascript.cpp"
|
||||
#include "detail/juce_QuickJSHelpers.h"
|
||||
|
||||
#include "javascript/juce_JSObject.cpp"
|
||||
#include "javascript/juce_JSCursor.cpp"
|
||||
#include "javascript/juce_JavascriptEngine.cpp"
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
#include "javascript/juce_Javascript_test.cpp"
|
||||
|
|
|
|||
|
|
@ -62,4 +62,7 @@
|
|||
#define JUCE_JAVASCRIPT_H_INCLUDED
|
||||
|
||||
#include <juce_core/juce_core.h>
|
||||
#include "javascript/juce_Javascript.h"
|
||||
|
||||
#include "javascript/juce_JSObject.h"
|
||||
#include "javascript/juce_JSCursor.h"
|
||||
#include "javascript/juce_JavascriptEngine.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue