diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..677e36e29 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/ClearScript.sln b/ClearScript.sln index 254f2e4db..cdb0ef9a2 100644 --- a/ClearScript.sln +++ b/ClearScript.sln @@ -1,334 +1,343 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32519.379 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "NetFramework\ClearScriptTest\ClearScriptTest.csproj", "{EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}" - ProjectSection(ProjectDependencies) = postProject - {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetFramework\ClearScriptConsole\ClearScriptConsole.csproj", "{28980C99-77E7-4B62-8484-AF06C5745B8C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5488F9BE-286E-459B-8384-E9EDA331BD5B}" - ProjectSection(SolutionItems) = preProject - ClearScript\doc\Build.docx = ClearScript\doc\Build.docx - ClearScript\doc\Examples.docx = ClearScript\doc\Examples.docx - ClearScript\doc\FAQtorial.docx = ClearScript\doc\FAQtorial.docx - License.txt = License.txt - ReadMe.md = ReadMe.md - ClearScript\doc\Reference.chm = ClearScript\doc\Reference.chm - Version.tt = Version.tt - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "NetFramework\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Core", ".NET Core", "{38987D23-2ED7-473A-9DE5-863E338EF18A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetCore\ClearScriptConsole\ClearScriptConsole.csproj", "{497012BC-959C-43A0-90A6-156A35DF2F43}" - ProjectSection(ProjectDependencies) = postProject - {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "NetCore\ClearScriptTest\ClearScriptTest.csproj", "{269669D3-78D8-4AF3-A2AF-08D3446BD6BC}" - ProjectSection(ProjectDependencies) = postProject - {497012BC-959C-43A0-90A6-156A35DF2F43} = {497012BC-959C-43A0-90A6-156A35DF2F43} - {6576FFFD-BA73-4123-8E4B-8589E5163C04} = {6576FFFD-BA73-4123-8E4B-8589E5163C04} - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} = {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Framework", ".NET Framework", "{526BA3EF-4E1D-48C1-9923-2485B63993EE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "NetCore\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{925DD842-4585-4D44-80BB-78E1FB7E9438}" - ProjectSection(ProjectDependencies) = postProject - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClearScriptV8", "ClearScriptV8", "{46C568CE-BA46-498F-9D8F-6293DED1BB94}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-x86", "ClearScriptV8\win-x86\ClearScriptV8.win-x86.vcxproj", "{2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}" - ProjectSection(ProjectDependencies) = postProject - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-x64", "ClearScriptV8\win-x64\ClearScriptV8.win-x64.vcxproj", "{CDCF4EEA-1CA4-412E-8C77-78893A67A577}" - ProjectSection(ProjectDependencies) = postProject - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetFramework\ClearScript.Core\ClearScript.Core.csproj", "{F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows", "NetFramework\ClearScript.Windows\ClearScript.Windows.csproj", "{BC560FF8-AB7A-4DA9-A1FD-99221447D370}" - ProjectSection(ProjectDependencies) = postProject - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetFramework\ClearScript.V8\ClearScript.V8.csproj", "{59CC81A3-3D97-469A-9C8B-533F920085F1}" - ProjectSection(ProjectDependencies) = postProject - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} = {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} = {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} - {CDCF4EEA-1CA4-412E-8C77-78893A67A577} = {CDCF4EEA-1CA4-412E-8C77-78893A67A577} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetCore\ClearScript.Core\ClearScript.Core.csproj", "{7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}" - ProjectSection(ProjectDependencies) = postProject - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows", "NetCore\ClearScript.Windows\ClearScript.Windows.csproj", "{6576FFFD-BA73-4123-8E4B-8589E5163C04}" - ProjectSection(ProjectDependencies) = postProject - {BC560FF8-AB7A-4DA9-A1FD-99221447D370} = {BC560FF8-AB7A-4DA9-A1FD-99221447D370} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetCore\ClearScript.V8\ClearScript.V8.csproj", "{C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}" - ProjectSection(ProjectDependencies) = postProject - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} - {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unix", "Unix", "{48C9730D-CA6C-47ED-B72C-DB9B6EE24D47}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "Unix\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}" - ProjectSection(ProjectDependencies) = postProject - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "Unix\ClearScriptConsole\ClearScriptConsole.csproj", "{3CD8AB65-BA34-4BB9-862F-D31CE861560F}" - ProjectSection(ProjectDependencies) = postProject - {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "Unix\ClearScriptTest\ClearScriptTest.csproj", "{052E036D-6D60-4FCA-AA8E-4CF56BC2058D}" - ProjectSection(ProjectDependencies) = postProject - {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {3CD8AB65-BA34-4BB9-862F-D31CE861560F} - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-arm64", "ClearScriptV8\win-arm64\ClearScriptV8.win-arm64.vcxproj", "{725B6D7A-ECC7-4A28-AF52-B1CB22C37134}" - ProjectSection(ProjectDependencies) = postProject - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UWP", "UWP", "{DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearScript.Core", "UWP\ClearScript.Core\ClearScript.Core.csproj", "{D3391831-65CE-4C1E-A21B-01A283F3E193}" - ProjectSection(ProjectDependencies) = postProject - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearScript.V8", "UWP\ClearScript.V8\ClearScript.V8.csproj", "{CF1FD52F-A933-48D9-92A4-A39565896A42}" - ProjectSection(ProjectDependencies) = postProject - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} - {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} - {D3391831-65CE-4C1E-A21B-01A283F3E193} = {D3391831-65CE-4C1E-A21B-01A283F3E193} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetCore\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{B9C99091-E616-4DC2-A711-4DCDAC602E38}" - ProjectSection(ProjectDependencies) = postProject - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetFramework\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Standard", ".NET Standard", "{3047C214-A12B-4C8B-AEED-021FAA0B4CD3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetStandard\ClearScript.Core\ClearScript.Core.csproj", "{D757A0DB-AEBC-4D77-A187-A701B158D588}" - ProjectSection(ProjectDependencies) = postProject - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetStandard\ClearScript.V8\ClearScript.V8.csproj", "{0DEC74E5-FF8A-4B61-B847-875BAD0AE781}" - ProjectSection(ProjectDependencies) = postProject - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} - {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetStandard\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{6F6B59D0-6538-4D02-91D2-07D24DAFE39A}" - ProjectSection(ProjectDependencies) = postProject - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest.NetStandard", "NetStandard\ClearScriptTest.NetStandard\ClearScriptTest.NetStandard.csproj", "{BF28C9F2-2935-4FDE-B812-977D601F9208}" - ProjectSection(ProjectDependencies) = postProject - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} = {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} = {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest.NetStandard", "Unix\ClearScriptTest.NetStandard\ClearScriptTest.NetStandard.csproj", "{EF6090B9-7349-4868-9C43-D7D3F048C54F}" - ProjectSection(ProjectDependencies) = postProject - {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {3CD8AB65-BA34-4BB9-862F-D31CE861560F} - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetStandard\ClearScriptConsole\ClearScriptConsole.csproj", "{C0E7BCAD-B4B3-4291-A87A-384D5F99C413}" - ProjectSection(ProjectDependencies) = postProject - {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8.ICUData", "NetStandard\ClearScript.V8.ICUData\ClearScript.V8.ICUData.csproj", "{47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Release|Any CPU.Build.0 = Release|Any CPU - {28980C99-77E7-4B62-8484-AF06C5745B8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {28980C99-77E7-4B62-8484-AF06C5745B8C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28980C99-77E7-4B62-8484-AF06C5745B8C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {28980C99-77E7-4B62-8484-AF06C5745B8C}.Release|Any CPU.Build.0 = Release|Any CPU - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Release|Any CPU.Build.0 = Release|Any CPU - {497012BC-959C-43A0-90A6-156A35DF2F43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {497012BC-959C-43A0-90A6-156A35DF2F43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {497012BC-959C-43A0-90A6-156A35DF2F43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {497012BC-959C-43A0-90A6-156A35DF2F43}.Release|Any CPU.Build.0 = Release|Any CPU - {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Release|Any CPU.Build.0 = Release|Any CPU - {925DD842-4585-4D44-80BB-78E1FB7E9438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {925DD842-4585-4D44-80BB-78E1FB7E9438}.Debug|Any CPU.Build.0 = Debug|Any CPU - {925DD842-4585-4D44-80BB-78E1FB7E9438}.Release|Any CPU.ActiveCfg = Release|Any CPU - {925DD842-4585-4D44-80BB-78E1FB7E9438}.Release|Any CPU.Build.0 = Release|Any CPU - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Debug|Any CPU.Build.0 = Debug|Win32 - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Release|Any CPU.ActiveCfg = Release|Win32 - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Release|Any CPU.Build.0 = Release|Win32 - {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Debug|Any CPU.ActiveCfg = Debug|x64 - {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Debug|Any CPU.Build.0 = Debug|x64 - {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Release|Any CPU.ActiveCfg = Release|x64 - {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Release|Any CPU.Build.0 = Release|x64 - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Release|Any CPU.Build.0 = Release|Any CPU - {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Release|Any CPU.Build.0 = Release|Any CPU - {59CC81A3-3D97-469A-9C8B-533F920085F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {59CC81A3-3D97-469A-9C8B-533F920085F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59CC81A3-3D97-469A-9C8B-533F920085F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59CC81A3-3D97-469A-9C8B-533F920085F1}.Release|Any CPU.Build.0 = Release|Any CPU - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Release|Any CPU.Build.0 = Release|Any CPU - {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Release|Any CPU.Build.0 = Release|Any CPU - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Release|Any CPU.Build.0 = Release|Any CPU - {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Release|Any CPU.Build.0 = Release|Any CPU - {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Release|Any CPU.Build.0 = Release|Any CPU - {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Release|Any CPU.Build.0 = Release|Any CPU - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Debug|Any CPU.ActiveCfg = Debug|arm64 - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Debug|Any CPU.Build.0 = Debug|arm64 - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Release|Any CPU.ActiveCfg = Release|arm64 - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Release|Any CPU.Build.0 = Release|arm64 - {D3391831-65CE-4C1E-A21B-01A283F3E193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D3391831-65CE-4C1E-A21B-01A283F3E193}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D3391831-65CE-4C1E-A21B-01A283F3E193}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D3391831-65CE-4C1E-A21B-01A283F3E193}.Release|Any CPU.Build.0 = Release|Any CPU - {CF1FD52F-A933-48D9-92A4-A39565896A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF1FD52F-A933-48D9-92A4-A39565896A42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF1FD52F-A933-48D9-92A4-A39565896A42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF1FD52F-A933-48D9-92A4-A39565896A42}.Release|Any CPU.Build.0 = Release|Any CPU - {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Release|Any CPU.Build.0 = Release|Any CPU - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Release|Any CPU.Build.0 = Release|Any CPU - {D757A0DB-AEBC-4D77-A187-A701B158D588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D757A0DB-AEBC-4D77-A187-A701B158D588}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D757A0DB-AEBC-4D77-A187-A701B158D588}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D757A0DB-AEBC-4D77-A187-A701B158D588}.Release|Any CPU.Build.0 = Release|Any CPU - {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Release|Any CPU.Build.0 = Release|Any CPU - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Release|Any CPU.Build.0 = Release|Any CPU - {BF28C9F2-2935-4FDE-B812-977D601F9208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF28C9F2-2935-4FDE-B812-977D601F9208}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF28C9F2-2935-4FDE-B812-977D601F9208}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF28C9F2-2935-4FDE-B812-977D601F9208}.Release|Any CPU.Build.0 = Release|Any CPU - {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Release|Any CPU.Build.0 = Release|Any CPU - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Release|Any CPU.Build.0 = Release|Any CPU - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {28980C99-77E7-4B62-8484-AF06C5745B8C} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {497012BC-959C-43A0-90A6-156A35DF2F43} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {269669D3-78D8-4AF3-A2AF-08D3446BD6BC} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {925DD842-4585-4D44-80BB-78E1FB7E9438} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} - {CDCF4EEA-1CA4-412E-8C77-78893A67A577} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} - {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {BC560FF8-AB7A-4DA9-A1FD-99221447D370} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {59CC81A3-3D97-469A-9C8B-533F920085F1} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {6576FFFD-BA73-4123-8E4B-8589E5163C04} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} - {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} - {052E036D-6D60-4FCA-AA8E-4CF56BC2058D} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} - {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} - {D3391831-65CE-4C1E-A21B-01A283F3E193} = {DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5} - {CF1FD52F-A933-48D9-92A4-A39565896A42} = {DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5} - {B9C99091-E616-4DC2-A711-4DCDAC602E38} = {38987D23-2ED7-473A-9DE5-863E338EF18A} - {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} - {D757A0DB-AEBC-4D77-A187-A701B158D588} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - {0DEC74E5-FF8A-4B61-B847-875BAD0AE781} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - {BF28C9F2-2935-4FDE-B812-977D601F9208} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - {EF6090B9-7349-4868-9C43-D7D3F048C54F} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} - {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {3BAF1393-35E4-45F1-AC56-4A22646B56E5} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32519.379 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "NetFramework\ClearScriptTest\ClearScriptTest.csproj", "{EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}" + ProjectSection(ProjectDependencies) = postProject + {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetFramework\ClearScriptConsole\ClearScriptConsole.csproj", "{28980C99-77E7-4B62-8484-AF06C5745B8C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5488F9BE-286E-459B-8384-E9EDA331BD5B}" + ProjectSection(SolutionItems) = preProject + ClearScript\doc\Build.docx = ClearScript\doc\Build.docx + ClearScript\doc\Examples.docx = ClearScript\doc\Examples.docx + ClearScript\doc\FAQtorial.docx = ClearScript\doc\FAQtorial.docx + License.txt = License.txt + ReadMe.md = ReadMe.md + ClearScript\doc\Reference.chm = ClearScript\doc\Reference.chm + Version.tt = Version.tt + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "NetFramework\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Core", ".NET Core", "{38987D23-2ED7-473A-9DE5-863E338EF18A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetCore\ClearScriptConsole\ClearScriptConsole.csproj", "{497012BC-959C-43A0-90A6-156A35DF2F43}" + ProjectSection(ProjectDependencies) = postProject + {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "NetCore\ClearScriptTest\ClearScriptTest.csproj", "{269669D3-78D8-4AF3-A2AF-08D3446BD6BC}" + ProjectSection(ProjectDependencies) = postProject + {497012BC-959C-43A0-90A6-156A35DF2F43} = {497012BC-959C-43A0-90A6-156A35DF2F43} + {6576FFFD-BA73-4123-8E4B-8589E5163C04} = {6576FFFD-BA73-4123-8E4B-8589E5163C04} + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} = {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Framework", ".NET Framework", "{526BA3EF-4E1D-48C1-9923-2485B63993EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "NetCore\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{925DD842-4585-4D44-80BB-78E1FB7E9438}" + ProjectSection(ProjectDependencies) = postProject + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClearScriptV8", "ClearScriptV8", "{46C568CE-BA46-498F-9D8F-6293DED1BB94}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-x86", "ClearScriptV8\win-x86\ClearScriptV8.win-x86.vcxproj", "{2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}" + ProjectSection(ProjectDependencies) = postProject + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-x64", "ClearScriptV8\win-x64\ClearScriptV8.win-x64.vcxproj", "{CDCF4EEA-1CA4-412E-8C77-78893A67A577}" + ProjectSection(ProjectDependencies) = postProject + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetFramework\ClearScript.Core\ClearScript.Core.csproj", "{F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows", "NetFramework\ClearScript.Windows\ClearScript.Windows.csproj", "{BC560FF8-AB7A-4DA9-A1FD-99221447D370}" + ProjectSection(ProjectDependencies) = postProject + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetFramework\ClearScript.V8\ClearScript.V8.csproj", "{59CC81A3-3D97-469A-9C8B-533F920085F1}" + ProjectSection(ProjectDependencies) = postProject + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} = {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} = {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} + {CDCF4EEA-1CA4-412E-8C77-78893A67A577} = {CDCF4EEA-1CA4-412E-8C77-78893A67A577} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetCore\ClearScript.Core\ClearScript.Core.csproj", "{7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}" + ProjectSection(ProjectDependencies) = postProject + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows", "NetCore\ClearScript.Windows\ClearScript.Windows.csproj", "{6576FFFD-BA73-4123-8E4B-8589E5163C04}" + ProjectSection(ProjectDependencies) = postProject + {BC560FF8-AB7A-4DA9-A1FD-99221447D370} = {BC560FF8-AB7A-4DA9-A1FD-99221447D370} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetCore\ClearScript.V8\ClearScript.V8.csproj", "{C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}" + ProjectSection(ProjectDependencies) = postProject + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} + {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unix", "Unix", "{48C9730D-CA6C-47ED-B72C-DB9B6EE24D47}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptBenchmarks", "Unix\ClearScriptBenchmarks\ClearScriptBenchmarks.csproj", "{FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}" + ProjectSection(ProjectDependencies) = postProject + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "Unix\ClearScriptConsole\ClearScriptConsole.csproj", "{3CD8AB65-BA34-4BB9-862F-D31CE861560F}" + ProjectSection(ProjectDependencies) = postProject + {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest", "Unix\ClearScriptTest\ClearScriptTest.csproj", "{052E036D-6D60-4FCA-AA8E-4CF56BC2058D}" + ProjectSection(ProjectDependencies) = postProject + {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {3CD8AB65-BA34-4BB9-862F-D31CE861560F} + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClearScriptV8.win-arm64", "ClearScriptV8\win-arm64\ClearScriptV8.win-arm64.vcxproj", "{725B6D7A-ECC7-4A28-AF52-B1CB22C37134}" + ProjectSection(ProjectDependencies) = postProject + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UWP", "UWP", "{DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearScript.Core", "UWP\ClearScript.Core\ClearScript.Core.csproj", "{D3391831-65CE-4C1E-A21B-01A283F3E193}" + ProjectSection(ProjectDependencies) = postProject + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearScript.V8", "UWP\ClearScript.V8\ClearScript.V8.csproj", "{CF1FD52F-A933-48D9-92A4-A39565896A42}" + ProjectSection(ProjectDependencies) = postProject + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} + {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} + {D3391831-65CE-4C1E-A21B-01A283F3E193} = {D3391831-65CE-4C1E-A21B-01A283F3E193} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetCore\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{B9C99091-E616-4DC2-A711-4DCDAC602E38}" + ProjectSection(ProjectDependencies) = postProject + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetFramework\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".NET Standard", ".NET Standard", "{3047C214-A12B-4C8B-AEED-021FAA0B4CD3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Core", "NetStandard\ClearScript.Core\ClearScript.Core.csproj", "{D757A0DB-AEBC-4D77-A187-A701B158D588}" + ProjectSection(ProjectDependencies) = postProject + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8", "NetStandard\ClearScript.V8\ClearScript.V8.csproj", "{0DEC74E5-FF8A-4B61-B847-875BAD0AE781}" + ProjectSection(ProjectDependencies) = postProject + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} + {59CC81A3-3D97-469A-9C8B-533F920085F1} = {59CC81A3-3D97-469A-9C8B-533F920085F1} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.Windows.Core", "NetStandard\ClearScript.Windows.Core\ClearScript.Windows.Core.csproj", "{6F6B59D0-6538-4D02-91D2-07D24DAFE39A}" + ProjectSection(ProjectDependencies) = postProject + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest.NetStandard", "NetStandard\ClearScriptTest.NetStandard\ClearScriptTest.NetStandard.csproj", "{BF28C9F2-2935-4FDE-B812-977D601F9208}" + ProjectSection(ProjectDependencies) = postProject + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} = {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} = {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptTest.NetStandard", "Unix\ClearScriptTest.NetStandard\ClearScriptTest.NetStandard.csproj", "{EF6090B9-7349-4868-9C43-D7D3F048C54F}" + ProjectSection(ProjectDependencies) = postProject + {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {3CD8AB65-BA34-4BB9-862F-D31CE861560F} + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScriptConsole", "NetStandard\ClearScriptConsole\ClearScriptConsole.csproj", "{C0E7BCAD-B4B3-4291-A87A-384D5F99C413}" + ProjectSection(ProjectDependencies) = postProject + {28980C99-77E7-4B62-8484-AF06C5745B8C} = {28980C99-77E7-4B62-8484-AF06C5745B8C} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScript.V8.ICUData", "NetStandard\ClearScript.V8.ICUData\ClearScript.V8.ICUData.csproj", "{47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unity", "Unity", "{C2F3A73A-B503-48AB-88CF-600252015008}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageBuilder", "Unity\PackageBuilder\PackageBuilder.csproj", "{D21DFD33-8138-4EBA-AE97-A7CB0B38D56B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D}.Release|Any CPU.Build.0 = Release|Any CPU + {28980C99-77E7-4B62-8484-AF06C5745B8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28980C99-77E7-4B62-8484-AF06C5745B8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28980C99-77E7-4B62-8484-AF06C5745B8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28980C99-77E7-4B62-8484-AF06C5745B8C}.Release|Any CPU.Build.0 = Release|Any CPU + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29}.Release|Any CPU.Build.0 = Release|Any CPU + {497012BC-959C-43A0-90A6-156A35DF2F43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {497012BC-959C-43A0-90A6-156A35DF2F43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {497012BC-959C-43A0-90A6-156A35DF2F43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {497012BC-959C-43A0-90A6-156A35DF2F43}.Release|Any CPU.Build.0 = Release|Any CPU + {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {269669D3-78D8-4AF3-A2AF-08D3446BD6BC}.Release|Any CPU.Build.0 = Release|Any CPU + {925DD842-4585-4D44-80BB-78E1FB7E9438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {925DD842-4585-4D44-80BB-78E1FB7E9438}.Debug|Any CPU.Build.0 = Debug|Any CPU + {925DD842-4585-4D44-80BB-78E1FB7E9438}.Release|Any CPU.ActiveCfg = Release|Any CPU + {925DD842-4585-4D44-80BB-78E1FB7E9438}.Release|Any CPU.Build.0 = Release|Any CPU + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Debug|Any CPU.Build.0 = Debug|Win32 + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Release|Any CPU.ActiveCfg = Release|Win32 + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6}.Release|Any CPU.Build.0 = Release|Win32 + {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Debug|Any CPU.ActiveCfg = Debug|x64 + {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Debug|Any CPU.Build.0 = Debug|x64 + {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Release|Any CPU.ActiveCfg = Release|x64 + {CDCF4EEA-1CA4-412E-8C77-78893A67A577}.Release|Any CPU.Build.0 = Release|x64 + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2}.Release|Any CPU.Build.0 = Release|Any CPU + {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC560FF8-AB7A-4DA9-A1FD-99221447D370}.Release|Any CPU.Build.0 = Release|Any CPU + {59CC81A3-3D97-469A-9C8B-533F920085F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59CC81A3-3D97-469A-9C8B-533F920085F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59CC81A3-3D97-469A-9C8B-533F920085F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59CC81A3-3D97-469A-9C8B-533F920085F1}.Release|Any CPU.Build.0 = Release|Any CPU + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD}.Release|Any CPU.Build.0 = Release|Any CPU + {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6576FFFD-BA73-4123-8E4B-8589E5163C04}.Release|Any CPU.Build.0 = Release|Any CPU + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96}.Release|Any CPU.Build.0 = Release|Any CPU + {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB}.Release|Any CPU.Build.0 = Release|Any CPU + {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CD8AB65-BA34-4BB9-862F-D31CE861560F}.Release|Any CPU.Build.0 = Release|Any CPU + {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {052E036D-6D60-4FCA-AA8E-4CF56BC2058D}.Release|Any CPU.Build.0 = Release|Any CPU + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Debug|Any CPU.ActiveCfg = Debug|arm64 + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Debug|Any CPU.Build.0 = Debug|arm64 + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Release|Any CPU.ActiveCfg = Release|arm64 + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134}.Release|Any CPU.Build.0 = Release|arm64 + {D3391831-65CE-4C1E-A21B-01A283F3E193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3391831-65CE-4C1E-A21B-01A283F3E193}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3391831-65CE-4C1E-A21B-01A283F3E193}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3391831-65CE-4C1E-A21B-01A283F3E193}.Release|Any CPU.Build.0 = Release|Any CPU + {CF1FD52F-A933-48D9-92A4-A39565896A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF1FD52F-A933-48D9-92A4-A39565896A42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF1FD52F-A933-48D9-92A4-A39565896A42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF1FD52F-A933-48D9-92A4-A39565896A42}.Release|Any CPU.Build.0 = Release|Any CPU + {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9C99091-E616-4DC2-A711-4DCDAC602E38}.Release|Any CPU.Build.0 = Release|Any CPU + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A}.Release|Any CPU.Build.0 = Release|Any CPU + {D757A0DB-AEBC-4D77-A187-A701B158D588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D757A0DB-AEBC-4D77-A187-A701B158D588}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D757A0DB-AEBC-4D77-A187-A701B158D588}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D757A0DB-AEBC-4D77-A187-A701B158D588}.Release|Any CPU.Build.0 = Release|Any CPU + {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DEC74E5-FF8A-4B61-B847-875BAD0AE781}.Release|Any CPU.Build.0 = Release|Any CPU + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A}.Release|Any CPU.Build.0 = Release|Any CPU + {BF28C9F2-2935-4FDE-B812-977D601F9208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF28C9F2-2935-4FDE-B812-977D601F9208}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF28C9F2-2935-4FDE-B812-977D601F9208}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF28C9F2-2935-4FDE-B812-977D601F9208}.Release|Any CPU.Build.0 = Release|Any CPU + {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF6090B9-7349-4868-9C43-D7D3F048C54F}.Release|Any CPU.Build.0 = Release|Any CPU + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413}.Release|Any CPU.Build.0 = Release|Any CPU + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C}.Release|Any CPU.Build.0 = Release|Any CPU + {D21DFD33-8138-4EBA-AE97-A7CB0B38D56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D21DFD33-8138-4EBA-AE97-A7CB0B38D56B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D21DFD33-8138-4EBA-AE97-A7CB0B38D56B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D21DFD33-8138-4EBA-AE97-A7CB0B38D56B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {EDC7144E-FDA9-4CC7-B2CD-B5EBFD610A7D} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {28980C99-77E7-4B62-8484-AF06C5745B8C} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {7922A2F5-3585-4A60-98FB-1BDB4D5ECD29} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {497012BC-959C-43A0-90A6-156A35DF2F43} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {269669D3-78D8-4AF3-A2AF-08D3446BD6BC} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {925DD842-4585-4D44-80BB-78E1FB7E9438} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {2D63EA35-BA9C-4E77-B5A4-4938DBBFEFA6} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} + {CDCF4EEA-1CA4-412E-8C77-78893A67A577} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} + {F1022C3F-AFBC-4F23-B4DE-C6C0742AEFF2} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {BC560FF8-AB7A-4DA9-A1FD-99221447D370} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {59CC81A3-3D97-469A-9C8B-533F920085F1} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {7B3EA81F-F60B-46DB-B3F0-22F68E8A8FAD} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {6576FFFD-BA73-4123-8E4B-8589E5163C04} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {C8AE52BB-BFEE-4816-A9FE-8653CEE36C96} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {FDFA67F7-AEE6-407A-BF94-ACAD3D735CAB} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} + {3CD8AB65-BA34-4BB9-862F-D31CE861560F} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} + {052E036D-6D60-4FCA-AA8E-4CF56BC2058D} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} + {725B6D7A-ECC7-4A28-AF52-B1CB22C37134} = {46C568CE-BA46-498F-9D8F-6293DED1BB94} + {D3391831-65CE-4C1E-A21B-01A283F3E193} = {DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5} + {CF1FD52F-A933-48D9-92A4-A39565896A42} = {DAF9D89A-5A6E-4450-8DA5-DFD73F26DDF5} + {B9C99091-E616-4DC2-A711-4DCDAC602E38} = {38987D23-2ED7-473A-9DE5-863E338EF18A} + {5FF9CB8B-BC95-44AB-B254-CEB4ADF4A53A} = {526BA3EF-4E1D-48C1-9923-2485B63993EE} + {D757A0DB-AEBC-4D77-A187-A701B158D588} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {0DEC74E5-FF8A-4B61-B847-875BAD0AE781} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {6F6B59D0-6538-4D02-91D2-07D24DAFE39A} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {BF28C9F2-2935-4FDE-B812-977D601F9208} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {EF6090B9-7349-4868-9C43-D7D3F048C54F} = {48C9730D-CA6C-47ED-B72C-DB9B6EE24D47} + {C0E7BCAD-B4B3-4291-A87A-384D5F99C413} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {47FC5CB5-A6F2-4FEE-99F8-A758D3A7373C} = {3047C214-A12B-4C8B-AEED-021FAA0B4CD3} + {D21DFD33-8138-4EBA-AE97-A7CB0B38D56B} = {C2F3A73A-B503-48AB-88CF-600252015008} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3BAF1393-35E4-45F1-AC56-4A22646B56E5} + EndGlobalSection +EndGlobal diff --git a/ClearScript/DelegateFactory.tt b/ClearScript/DelegateFactory.tt index ce7235872..3c07b30cd 100644 --- a/ClearScript/DelegateFactory.tt +++ b/ClearScript/DelegateFactory.tt @@ -26,9 +26,9 @@ namespace Microsoft.ClearScript var allByValueExpr = (count == 0) ? "true" : "GetAllByValue(" + string.Join(", ", Enumerable.Range(1, count).Select(index => "typeof(T" + index + ")")) + ")"; var methodParamList = string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index + " a" + index)); var argList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index)); - var varDeclList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");")); + var varDeclList = string.Join("\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");")); var byRefArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "ref v" + index)); - var varAssignList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");")); + var varAssignList = string.Join("\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");")); #> [ExcludeFromCodeCoverage] @@ -97,9 +97,9 @@ namespace Microsoft.ClearScript var allByValueExpr = (count == 0) ? "true" : "GetAllByValue(" + string.Join(", ", Enumerable.Range(1, count).Select(index => "typeof(T" + index + ")")) + ")"; var methodParamList = string.Join(", ", Enumerable.Range(1, count).Select(index => "T" + index + " a" + index)); var argList = string.Join(", ", Enumerable.Range(1, count).Select(index => "a" + index)); - var varDeclList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");")); + var varDeclList = string.Join("\n ", Enumerable.Range(1, count).Select(index => "var v" + index + " = GetArgValue(a" + index + ");")); var byRefArgList = string.Join(", ", Enumerable.Range(1, count).Select(index => "ref v" + index)); - var varAssignList = string.Join("\r\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");")); + var varAssignList = string.Join("\n ", Enumerable.Range(1, count).Select(index => "SetArgValue(a" + index + ", v" + index + ");")); #> [ExcludeFromCodeCoverage] diff --git a/ClearScript/HostItem.InvokeMethod.cs b/ClearScript/HostItem.InvokeMethod.cs index 9d8890cae..56d8c8b9c 100644 --- a/ClearScript/HostItem.InvokeMethod.cs +++ b/ClearScript/HostItem.InvokeMethod.cs @@ -497,16 +497,26 @@ public bool IsUnblockedMethod(HostItem hostItem) return IsSuccess && !method.IsBlockedFromScript(hostItem, hostItem.DefaultAccess); } - public object Invoke(HostItem hostItem) - { - if (!IsSuccess) - { - throw exceptionFactory(); - } - - if (reflectionMethods.Contains(method, MemberComparer.Instance)) - { - hostItem.Engine.CheckReflection(); + public object Invoke(HostItem hostItem) + { + if (!IsSuccess) + { + throw exceptionFactory(); + } + + bool isReflectionMethod = false; + for (int i = 0; i < reflectionMethods.Length; i++) + { + if (MemberComparer.Instance.Equals(reflectionMethods[i], method)) + { + isReflectionMethod = true; + break; + } + } + + if (isReflectionMethod) + { + hostItem.Engine.CheckReflection(); } return InvokeHelpers.InvokeMethod(hostItem, method, hostTarget.InvokeTarget, args, method.GetScriptMemberFlags(hostItem)); diff --git a/ClearScript/HostItem.cs b/ClearScript/HostItem.cs index 621a59a3f..c2dead932 100644 --- a/ClearScript/HostItem.cs +++ b/ClearScript/HostItem.cs @@ -122,7 +122,7 @@ public Invocability Invocability { if (TargetInvocability == null) { - TargetInvocability = Target.GetInvocability(this, GetCommonBindFlags(), Flags.HasFlag(HostItemFlags.HideDynamicMembers)); + TargetInvocability = Target.GetInvocability(this, GetCommonBindFlags(), Flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers)); } return TargetInvocability.GetValueOrDefault(); @@ -173,13 +173,13 @@ public object InvokeMember(string name, BindingFlags invokeFlags, object[] args, if (!bypassTunneling) { int testLength; - if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) { - testLength = invokeFlags.HasFlag(BindingFlags.GetField) ? 0 : -1; + testLength = invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) ? 0 : -1; } else { - testLength = invokeFlags.HasFlag(BindingFlags.SetField) ? 1 : 0; + testLength = invokeFlags.HasFlagNonAlloc(BindingFlags.SetField) ? 1 : 0; } if ((args.Length > testLength) && (name != SpecialMemberNames.Default)) @@ -364,7 +364,7 @@ private Invocability? TargetInvocability private CustomAttributeLoader CurrentCustomAttributeLoader => Engine.CustomAttributeLoader; - private Type CurrentAccessContext => Flags.HasFlag(HostItemFlags.PrivateAccess) ? Target.Type : Engine.AccessContext; + private Type CurrentAccessContext => Flags.HasFlagNonAlloc(HostItemFlags.PrivateAccess) ? Target.Type : Engine.AccessContext; private ScriptAccess CurrentDefaultAccess => Engine.DefaultAccess; @@ -428,7 +428,7 @@ private static bool TargetSupportsExpandoMembers(HostTarget target, HostItemFlag return true; } - if (!flags.HasFlag(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type)) + if (!flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type)) { return true; } @@ -468,7 +468,7 @@ private void BindSpecialTarget() } else { - if (!Flags.HasFlag(HostItemFlags.HideDynamicMembers) && BindSpecialTarget(out IDynamicMetaObjectProvider dynamicMetaObjectProvider)) + if (!Flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers) && BindSpecialTarget(out IDynamicMetaObjectProvider dynamicMetaObjectProvider)) { var dynamicMetaObject = dynamicMetaObjectProvider.GetMetaObject(Expression.Constant(Target.InvokeTarget)); TargetDynamicMetaObject = new DynamicHostMetaObject(dynamicMetaObjectProvider, dynamicMetaObject); @@ -675,7 +675,7 @@ private string[] GetAllMethodNames(out string[] ownMethodNames) if ((TargetDynamic == null) && (TargetPropertyBag == null)) { names = names.Concat(GetLocalMethodNames()); - if (TargetFlags.HasFlag(HostTargetFlags.AllowExtensionMethods)) + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowExtensionMethods)) { var extensionMethodSummary = Engine.ExtensionMethodSummary; ExtensionMethodSummary = extensionMethodSummary; @@ -753,7 +753,7 @@ private void UpdateFieldNames(out bool updated) private void UpdateMethodNames(out bool updated) { if ((AllMethodNames == null) || - (TargetFlags.HasFlag(HostTargetFlags.AllowExtensionMethods) && (ExtensionMethodSummary != Engine.ExtensionMethodSummary))) + (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowExtensionMethods) && (ExtensionMethodSummary != Engine.ExtensionMethodSummary))) { AllMethodNames = GetAllMethodNames(out var ownMethodNames); OwnMethodNames = ownMethodNames; @@ -831,12 +831,12 @@ private BindingFlags GetCommonBindFlags() { var bindFlags = BindingFlags.Public | BindingFlags.NonPublic; - if (TargetFlags.HasFlag(HostTargetFlags.AllowStaticMembers)) + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowStaticMembers)) { bindFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; } - if (TargetFlags.HasFlag(HostTargetFlags.AllowInstanceMembers)) + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowInstanceMembers)) { bindFlags |= BindingFlags.Instance; } @@ -878,7 +878,7 @@ private void AdjustInvokeFlags(ref BindingFlags invokeFlags) invokeFlags |= onFlags; invokeFlags &= ~offFlags; - if (TargetFlags.HasFlag(HostTargetFlags.AllowStaticMembers)) + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowStaticMembers)) { invokeFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; } @@ -887,7 +887,7 @@ private void AdjustInvokeFlags(ref BindingFlags invokeFlags) invokeFlags &= ~BindingFlags.Static; } - if (TargetFlags.HasFlag(HostTargetFlags.AllowInstanceMembers)) + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowInstanceMembers)) { invokeFlags |= BindingFlags.Instance; } @@ -905,7 +905,7 @@ private void AdjustInvokeFlags(ref BindingFlags invokeFlags) invokeFlags &= ~BindingFlags.IgnoreCase; } - if (invokeFlags.HasFlag(BindingFlags.GetProperty)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetProperty)) { invokeFlags |= BindingFlags.GetField; } @@ -936,7 +936,7 @@ private object InvokeReflectMember(string name, BindingFlags invokeFlags, object } var bindArgs = args; - if ((args.Length > 0) && (invokeFlags.HasFlag(BindingFlags.InvokeMethod) || invokeFlags.HasFlag(BindingFlags.CreateInstance))) + if ((args.Length > 0) && (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod) || invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance))) { bindArgs = Engine.MarshalToHost(wrappedArgs, true); if (argOffset > 0) @@ -968,7 +968,7 @@ private object InvokeReflectMember(string name, BindingFlags invokeFlags, object private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object[] args) { - if (invokeFlags.HasFlag(BindingFlags.CreateInstance)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance)) { if (name == SpecialMemberNames.Default) { @@ -978,7 +978,7 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object throw new InvalidOperationException("Invalid constructor invocation"); } - if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) { if (name == SpecialMemberNames.Default) { @@ -988,7 +988,7 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object } catch { - if (invokeFlags.HasFlag(BindingFlags.GetField) && (args.Length < 1)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) && (args.Length < 1)) { return Target; } @@ -1003,7 +1003,7 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object } catch { - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { return TargetDynamic.GetProperty(name, args); } @@ -1012,12 +1012,12 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object } } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { return TargetDynamic.GetProperty(name, args); } - if (invokeFlags.HasFlag(BindingFlags.SetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) { if (args.Length > 0) { @@ -1033,13 +1033,13 @@ private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs) { - if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) { object value; if (name == SpecialMemberNames.Default) { - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { if (args.Length < 1) { @@ -1075,7 +1075,7 @@ private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, ob return result; } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { if (args.Length < 1) { @@ -1096,7 +1096,7 @@ private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, ob throw new NotSupportedException("The object does not support the requested invocation operation"); } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { if (name == SpecialMemberNames.Default) { @@ -1126,7 +1126,7 @@ private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, ob throw new InvalidOperationException("Invalid argument count"); } - if (invokeFlags.HasFlag(BindingFlags.SetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) { if (name == SpecialMemberNames.Default) { @@ -1166,14 +1166,14 @@ private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, ob private object InvokeListElement(int index, BindingFlags invokeFlags, object[] args, object[] bindArgs) { - if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) { if (InvokeHelpers.TryInvokeObject(this, TargetList[index], invokeFlags, args, bindArgs, true, out var result)) { return result; } - if (invokeFlags.HasFlag(BindingFlags.GetField) && (args.Length < 1)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) && (args.Length < 1)) { return TargetList[index]; } @@ -1181,7 +1181,7 @@ private object InvokeListElement(int index, BindingFlags invokeFlags, object[] a throw new NotSupportedException("The object does not support the requested invocation operation"); } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { if (args.Length < 1) { @@ -1191,7 +1191,7 @@ private object InvokeListElement(int index, BindingFlags invokeFlags, object[] a throw new InvalidOperationException("Invalid argument count"); } - if (invokeFlags.HasFlag(BindingFlags.SetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) { if (args.Length == 1) { @@ -1209,7 +1209,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] isCacheable = false; object result; - if (invokeFlags.HasFlag(BindingFlags.CreateInstance)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance)) { if (name == SpecialMemberNames.Default) { @@ -1274,7 +1274,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] throw new InvalidOperationException("Invalid constructor invocation"); } - if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) { if (name == SpecialMemberNames.Default) { @@ -1283,7 +1283,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] return result; } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { result = GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); if (!(result is Nonexistent)) @@ -1317,7 +1317,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] return CreateAsyncEnumerator(); } - if ((TargetDynamicMetaObject != null) && TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlag(BindingFlags.IgnoreCase))) + if ((TargetDynamicMetaObject != null) && TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlagNonAlloc(BindingFlags.IgnoreCase))) { if (TargetDynamicMetaObject.TryInvokeMember(this, name, invokeFlags, args, out result)) { @@ -1345,7 +1345,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] try { - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); } @@ -1365,7 +1365,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] } } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); } @@ -1373,12 +1373,12 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] throw new MissingMethodException(MiscHelpers.FormatInvariant("The object has no suitable method named '{0}'", name)); } - if (invokeFlags.HasFlag(BindingFlags.GetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) { return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); } - if (invokeFlags.HasFlag(BindingFlags.SetField)) + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) { return SetHostProperty(name, invokeFlags, args, bindArgs); } @@ -1462,7 +1462,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a int index; object result; - if (TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlag(BindingFlags.IgnoreCase))) + if (TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlagNonAlloc(BindingFlags.IgnoreCase))) { if (TargetDynamicMetaObject.TryGetMember(name, out result)) { @@ -1866,6 +1866,9 @@ private object CreateScriptableEnumerator() { if ((Target is HostObject) || (Target is IHostVariable) || (Target is IByRefArg)) { + if (Target.InvokeTarget is IScriptableEnumerator scriptableEnumerator) + return scriptableEnumerator; + if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IEnumerable<>), out var typeArgs)) { var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess); diff --git a/ClearScript/Properties/AssemblyInfo.V8.ICUData.cs b/ClearScript/Properties/AssemblyInfo.V8.ICUData.cs index 10c1e3a00..01d7044f6 100644 --- a/ClearScript/Properties/AssemblyInfo.V8.ICUData.cs +++ b/ClearScript/Properties/AssemblyInfo.V8.ICUData.cs @@ -5,6 +5,14 @@ + + + + + + + + using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -13,6 +21,7 @@ [assembly: AssemblyProduct("ClearScript")] [assembly: AssemblyCopyright("(c) Microsoft Corporation")] [assembly: InternalsVisibleTo("ClearScript.V8")] +[assembly: InternalsVisibleTo("Decentraland.ClearScript")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("7.4.5")] diff --git a/ClearScript/Properties/AssemblyInfo.V8.ICUData.tt b/ClearScript/Properties/AssemblyInfo.V8.ICUData.tt index d26632502..8bab82952 100644 --- a/ClearScript/Properties/AssemblyInfo.V8.ICUData.tt +++ b/ClearScript/Properties/AssemblyInfo.V8.ICUData.tt @@ -38,6 +38,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyProduct("ClearScript")] [assembly: AssemblyCopyright("(c) Microsoft Corporation")] [assembly: InternalsVisibleTo("<#= "ClearScript.V8" + publicKeySpec #>")] +[assembly: InternalsVisibleTo("Decentraland.ClearScript")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("<#= version.ToString(3) #>")] diff --git a/ClearScript/Util/EnumUtils.cs b/ClearScript/Util/EnumUtils.cs new file mode 100644 index 000000000..cfab726bf --- /dev/null +++ b/ClearScript/Util/EnumUtils.cs @@ -0,0 +1,25 @@ +using System; + +internal static class EnumUtils +{ + public static unsafe bool HasFlagNonAlloc(this T x, T y) where T : unmanaged, Enum + { + switch (sizeof(T)) + { + case sizeof(byte): + return (*(byte*) &x & *(byte*) &y) != 0; + + case sizeof(short): + return (*(short*) &x & *(short*) &y) != 0; + + case sizeof(int): + return (*(int*) &x & *(int*) &y) != 0; + + case sizeof(long): + return (*(long*) &x & *(long*) &y) != 0L; + + default: + return false; + } + } +} \ No newline at end of file diff --git a/ClearScript/Util/ObjectHelpers.Common.cs b/ClearScript/Util/ObjectHelpers.Common.cs index bd53aeafa..871673450 100644 --- a/ClearScript/Util/ObjectHelpers.Common.cs +++ b/ClearScript/Util/ObjectHelpers.Common.cs @@ -11,6 +11,9 @@ internal static partial class ObjectHelpers { private static bool GetPrimaryInteropAssembly(Guid libid, int major, int minor, out string name, out string codeBase) { +#if UNITY_5_3_OR_NEWER // There is no just "is Unity" symbol. + throw new NotSupportedException("What the hell are you doing with COM in a Unity game??"); +#else name = null; codeBase = null; @@ -37,7 +40,8 @@ private static bool GetPrimaryInteropAssembly(Guid libid, int major, int minor, } } - return name != null; + return name != null; +#endif } } } diff --git a/ClearScript/V8/SplitProxy/IV8HostObject.cs b/ClearScript/V8/SplitProxy/IV8HostObject.cs new file mode 100644 index 000000000..4fc67aece --- /dev/null +++ b/ClearScript/V8/SplitProxy/IV8HostObject.cs @@ -0,0 +1,116 @@ +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + /// + /// Implement this interface to talk to ClearScript's native wrapper around V8 directly. + /// + public interface IV8HostObject + { + /// + /// Implement this to support getting the values of named properties. + /// + /// The name of the property JavaScript wants the value of. + /// Write the value of the property here. + /// If you set this to to true, V8 will cache the value not ask for it + /// again. + void GetNamedProperty(StdString name, V8Value value, out bool isConst) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support setting the values of named properties. + /// + /// The name of the property JavaScript wants to set. + /// The value JavaScript wants to set the property to. + void SetNamedProperty(StdString name, V8Value.Decoded value) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support deleting named properties. + /// + /// The name of the property JavaScript wants to delete. + /// TODO + bool DeleteNamedProperty(StdString name) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support getting the values of indexed properties. + /// + /// The index of the property JavaScript wants the value of. + /// Write the value of the property here. + void GetIndexedProperty(int index, V8Value value) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support setting the values of indexed properties. + /// + /// The index of the property JavaScript wants to set. + /// The value JavaScript wants to set the property to. + void SetIndexedProperty(int index, V8Value.Decoded value) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support deleting indexed properties. + /// + /// The index of the property JavaScript wants to delete. + /// TODO + bool DeleteIndexedProperty(int index) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support being enumerated. + /// + /// Write the enumerator here. + /// + /// The enumerator class should implement and implement MoveNext(), + /// ScriptableDispose(), and CurrentValue. + /// + void GetEnumerator(V8Value result) => + throw new NotImplementedException("Enumerator is not implemented"); + + /// + /// Implement this to support being async enumerated. + /// + /// Write the async enumerator here. + void GetAsyncEnumerator(V8Value result) => + throw new NotImplementedException("Async enumerator is not implemented"); + + /// + /// Implement this to support listing of all your named proeprties. + /// + /// Write the names of your properties here. + void GetNamedPropertyNames(StdStringArray names) => + throw new NotImplementedException("Listing named properties is not implemented"); + + /// + /// Implement this to support listing all your indexed properties. + /// + /// Write the indices of your properties here. + void GetIndexedPropertyIndices(StdInt32Array indices) => + throw new NotImplementedException("Listing indexed properties is not implemented"); + + /// + /// I don't know when ClearScript calls this. + /// + /// The name of the method JavaScript wants to invoke. + /// The arguments JavaScript is passing to the method. + /// Write the return value, if not , of the method here. + /// + void InvokeMethod(StdString name, ReadOnlySpan args, V8Value result) + { + GetNamedProperty(name, result, out _); + object method = result.Decode().GetHostObject(); + result.SetNonexistent(); + ((InvokeHostObject)method)(args, result); + } + } + + /// + /// Return a delegate of this type from a property to tell JavaScript that it is a callable + /// function. + /// + /// The arguments JavaScript will pass to your method when invoking it. + /// Write the return value, if not , of the method here. + /// + public delegate void InvokeHostObject(ReadOnlySpan args, V8Value result); +} diff --git a/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs b/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs index 6194c103a..2aab1a990 100644 --- a/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs +++ b/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs @@ -19,6 +19,7 @@ internal interface IV8SplitProxyNative StdString.Ptr StdString_New(string value); string StdString_GetValue(StdString.Ptr pString); + void StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length); void StdString_SetValue(StdString.Ptr pString, string value); void StdString_Delete(StdString.Ptr pString); @@ -171,6 +172,7 @@ internal interface IV8SplitProxyNative void V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext); void V8Context_CancelAwaitDebugger(V8Context.Handle hContext); object V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate); + void V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult); V8Script.Handle V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code); V8Script.Handle V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); V8Script.Handle V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); @@ -199,17 +201,21 @@ internal interface IV8SplitProxyNative #region V8 object methods object V8Object_GetNamedProperty(V8Object.Handle hObject, string name); + void V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue); bool V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value); void V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value); bool V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name); string[] V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices); object V8Object_GetIndexedProperty(V8Object.Handle hObject, int index); + void V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue); void V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value); bool V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index); int[] V8Object_GetPropertyIndices(V8Object.Handle hObject); object V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args); + void V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult); object V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args); void V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length); + void V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length); void V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction); #endregion diff --git a/ClearScript/V8/SplitProxy/NativeCallbackImpl.cs b/ClearScript/V8/SplitProxy/NativeCallbackImpl.cs index 6b52e0b3f..5b2c23a2f 100644 --- a/ClearScript/V8/SplitProxy/NativeCallbackImpl.cs +++ b/ClearScript/V8/SplitProxy/NativeCallbackImpl.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -21,7 +21,10 @@ public NativeCallbackImpl(NativeCallback.Handle hCallback) public void Invoke() { - V8SplitProxyNative.InvokeNoThrow(instance => instance.NativeCallback_Invoke(Handle)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.NativeCallback_Invoke(Handle); + } } #endregion diff --git a/ClearScript/V8/SplitProxy/Uint8Array.cs b/ClearScript/V8/SplitProxy/Uint8Array.cs new file mode 100644 index 000000000..f6b89a721 --- /dev/null +++ b/ClearScript/V8/SplitProxy/Uint8Array.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + /// + /// Wraps a Uint8Array, an array of . + /// + public readonly ref struct Uint8Array + { + private readonly V8Object.Handle ptr; + + internal Uint8Array(V8Object.Handle pArray) + { + ptr = pArray; + using var arrayBuffer = V8Value.New(); + + V8SplitProxyNative.Instance.V8Object_GetArrayBufferOrViewInfo(pArray, arrayBuffer.ptr, + out _, out _, out ulong length); + + Length = (int)length; + } + + /// + /// Copy the contents of the wrapped Uint8Array to a managed array. + /// + /// The destination array. It must be large enough to contain the entire + /// contents of the wrapped Uint8Array. + public void CopyTo(byte[] array) + { + int length = Length; + + if (length > array.Length) + throw new IndexOutOfRangeException( + $"Tried to copy {length} items to a {array.Length} item array"); + + // TODO: Don't allocate a lambda every time. + IntPtr pAction = V8ProxyHelpers.AddRefHostObject(new Action(data => + Marshal.Copy(data, array, 0, length))); + + try + { + V8SplitProxyNative.Instance.V8Object_InvokeWithArrayBufferOrViewData(ptr, pAction); + } + finally + { + V8ProxyHelpers.ReleaseHostObject(pAction); + } + } + + /// + /// The length of the wrapped Uint8Array. + /// + public int Length { get; } + } +} diff --git a/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs b/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs index a56173e6b..d8f591a95 100644 --- a/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs +++ b/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs @@ -11,7 +11,7 @@ internal sealed class V8ContextProxyImpl : V8ContextProxy { private V8EntityHolder holder; - private V8Context.Handle Handle => (V8Context.Handle)holder.Handle; + internal V8Context.Handle Handle => (V8Context.Handle)holder.Handle; public V8ContextProxyImpl(V8IsolateProxy isolateProxy, string name, V8ScriptEngineFlags flags, int debugPort) { @@ -22,76 +22,135 @@ public V8ContextProxyImpl(V8IsolateProxy isolateProxy, string name, V8ScriptEngi public override UIntPtr MaxIsolateHeapSize { - get => V8SplitProxyNative.Invoke(instance => instance.V8Context_GetMaxIsolateHeapSize(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetMaxIsolateHeapSize(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetMaxIsolateHeapSize(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetMaxIsolateHeapSize(Handle, value); + } + } } public override TimeSpan IsolateHeapSizeSampleInterval { - get => V8SplitProxyNative.Invoke(instance => TimeSpan.FromMilliseconds(instance.V8Context_GetIsolateHeapSizeSampleInterval(Handle))); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetIsolateHeapSizeSampleInterval(Handle, value.TotalMilliseconds)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return TimeSpan.FromMilliseconds(instance.V8Context_GetIsolateHeapSizeSampleInterval(Handle)); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetIsolateHeapSizeSampleInterval(Handle, value.TotalMilliseconds); + } + } } public override UIntPtr MaxIsolateStackUsage { - get => V8SplitProxyNative.Invoke(instance => instance.V8Context_GetMaxIsolateStackUsage(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetMaxIsolateStackUsage(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetMaxIsolateStackUsage(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetMaxIsolateStackUsage(Handle, value); + } + } } public override void InvokeWithLock(Action action) { using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) { - var pAction = actionScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Context_InvokeWithLock(Handle, pAction)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_InvokeWithLock(Handle, actionScope.Value); + } } } public override object GetRootItem() { - return V8SplitProxyNative.Invoke(instance => instance.V8Context_GetRootItem(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetRootItem(Handle); + } } public override void AddGlobalItem(string name, object item, bool globalMembers) { - V8SplitProxyNative.Invoke(instance => instance.V8Context_AddGlobalItem(Handle, name, item, globalMembers)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_AddGlobalItem(Handle, name, item, globalMembers); + } } public override void AwaitDebuggerAndPause() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_AwaitDebuggerAndPause(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_AwaitDebuggerAndPause(Handle); + } } public override void CancelAwaitDebugger() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_CancelAwaitDebugger(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CancelAwaitDebugger(Handle); + } } public override object Execute(UniqueDocumentInfo documentInfo, string code, bool evaluate) { - return V8SplitProxyNative.Invoke(instance => instance.V8Context_ExecuteCode( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - evaluate - )); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_ExecuteCode( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + evaluate + ); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code) { - return new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Context_Compile( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code - ))); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_Compile( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) @@ -102,21 +161,20 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return Compile(documentInfo, code); } - byte[] tempCacheBytes = null; - var script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Context_CompileProducingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - out tempCacheBytes - ))); - - cacheBytes = tempCacheBytes; - return script; + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileProducingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + out cacheBytes + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) @@ -127,22 +185,21 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return Compile(documentInfo, code); } - var tempCacheAccepted = false; - var script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Context_CompileConsumingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - cacheBytes, - out tempCacheAccepted - ))); - - cacheAccepted = tempCacheAccepted; - return script; + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileConsumingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + cacheBytes, + out cacheAccepted + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) @@ -168,21 +225,22 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return script; } - var tempCacheResult = V8CacheResult.Disabled; - script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Context_CompileUpdatingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - ref tempCacheBytes, - out tempCacheResult - ))); - - cacheResult = tempCacheResult; + using (V8SplitProxyNative.Invoke(out var instance)) + { + script = new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileUpdatingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + ref cacheBytes, + out cacheResult + )); + } + if (cacheResult == V8CacheResult.Updated) { cacheBytes = tempCacheBytes; @@ -198,33 +256,68 @@ public override object Execute(V8.V8Script script, bool evaluate) throw new ArgumentException("Invalid compiled script", nameof(script)); } - return V8SplitProxyNative.Invoke(instance => instance.V8Context_ExecuteScript( - Handle, - scriptImpl.Handle, - evaluate - )); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_ExecuteScript( + Handle, + scriptImpl.Handle, + evaluate + ); + } } public override void Interrupt() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_Interrupt(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_Interrupt(Handle); + } } public override void CancelInterrupt() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_CancelInterrupt(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CancelInterrupt(Handle); + } } public override bool EnableIsolateInterruptPropagation { - get => V8SplitProxyNative.Invoke(instance => instance.V8Context_GetEnableIsolateInterruptPropagation(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetEnableIsolateInterruptPropagation(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetEnableIsolateInterruptPropagation(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetEnableIsolateInterruptPropagation(Handle, value); + } + } } public override bool DisableIsolateHeapSizeViolationInterrupt { - get => V8SplitProxyNative.Invoke(instance => instance.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(Handle, value); + } + } } public override V8RuntimeHeapInfo GetIsolateHeapInfo() @@ -236,7 +329,11 @@ public override V8RuntimeHeapInfo GetIsolateHeapInfo() var usedHeapSize = 0UL; var heapSizeLimit = 0UL; var totalExternalSize = 0UL; - V8SplitProxyNative.Invoke(instance => instance.V8Context_GetIsolateHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetIsolateHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } return new V8RuntimeHeapInfo { @@ -253,30 +350,49 @@ public override V8RuntimeHeapInfo GetIsolateHeapInfo() public override V8Runtime.Statistics GetIsolateStatistics() { var statistics = new V8Runtime.Statistics(); - V8SplitProxyNative.Invoke(instance => instance.V8Context_GetIsolateStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetIsolateStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts); + } + return statistics; } public override V8ScriptEngine.Statistics GetStatistics() { var statistics = new V8ScriptEngine.Statistics(); - V8SplitProxyNative.Invoke(instance => instance.V8Context_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ModuleCount, out statistics.ModuleCacheSize)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ModuleCount, out statistics.ModuleCacheSize); + } + return statistics; } public override void CollectGarbage(bool exhaustive) { - V8SplitProxyNative.Invoke(instance => instance.V8Context_CollectGarbage(Handle, exhaustive)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CollectGarbage(Handle, exhaustive); + } } public override void OnAccessSettingsChanged() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_OnAccessSettingsChanged(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_OnAccessSettingsChanged(Handle); + } } public override bool BeginCpuProfile(string name, V8CpuProfileFlags flags) { - return V8SplitProxyNative.Invoke(instance => instance.V8Context_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection))); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection)); + } } public override V8.V8CpuProfile EndCpuProfile(string name) @@ -286,8 +402,10 @@ public override V8.V8CpuProfile EndCpuProfile(string name) Action action = pProfile => V8CpuProfile.ProcessProfile(Handle, pProfile, profile); using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) { - var pAction = actionScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Context_EndCpuProfile(Handle, name, pAction)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_EndCpuProfile(Handle, name, actionScope.Value); + } } return profile; @@ -295,21 +413,39 @@ public override V8.V8CpuProfile EndCpuProfile(string name) public override void CollectCpuProfileSample() { - V8SplitProxyNative.Invoke(instance => instance.V8Context_CollectCpuProfileSample(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CollectCpuProfileSample(Handle); + } } public override uint CpuProfileSampleInterval { - get => V8SplitProxyNative.Invoke(instance => instance.V8Context_GetCpuProfileSampleInterval(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Context_SetCpuProfileSampleInterval(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetCpuProfileSampleInterval(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetCpuProfileSampleInterval(Handle, value); + } + } } public override void WriteIsolateHeapSnapshot(Stream stream) { using (var streamScope = V8ProxyHelpers.CreateAddRefHostObjectScope(stream)) { - var pStream = streamScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Context_WriteIsolateHeapSnapshot(Handle, pStream)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_WriteIsolateHeapSnapshot(Handle, streamScope.Value); + } } } diff --git a/ClearScript/V8/SplitProxy/V8DebugListenerImpl.cs b/ClearScript/V8/SplitProxy/V8DebugListenerImpl.cs index abd35f093..ba1224c56 100644 --- a/ClearScript/V8/SplitProxy/V8DebugListenerImpl.cs +++ b/ClearScript/V8/SplitProxy/V8DebugListenerImpl.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -20,17 +20,26 @@ public V8DebugListenerImpl(V8DebugCallback.Handle hCallback) public void ConnectClient() { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8DebugCallback_ConnectClient(Handle)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_ConnectClient(Handle); + } } public void SendCommand(string command) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8DebugCallback_SendCommand(Handle, command)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_SendCommand(Handle, command); + } } public void DisconnectClient() { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8DebugCallback_DisconnectClient(Handle)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_DisconnectClient(Handle); + } } #endregion diff --git a/ClearScript/V8/SplitProxy/V8EntityHolder.cs b/ClearScript/V8/SplitProxy/V8EntityHolder.cs index 64ae9d6b1..657951dd9 100644 --- a/ClearScript/V8/SplitProxy/V8EntityHolder.cs +++ b/ClearScript/V8/SplitProxy/V8EntityHolder.cs @@ -30,19 +30,23 @@ private V8EntityHolder(string name) public void ReleaseEntity() { - var tempHandle = handle; - if (tempHandle != V8Entity.Handle.Empty) + if (handle != V8Entity.Handle.Empty) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Entity_Release(tempHandle)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Entity_Release(handle); + } } } public static void Destroy(ref V8EntityHolder holder) { - var tempHandle = holder.handle; - if (tempHandle != V8Entity.Handle.Empty) + if (holder.handle != V8Entity.Handle.Empty) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Entity_DestroyHandle(tempHandle)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Entity_DestroyHandle(holder.handle); + } } if (holder.registered) diff --git a/ClearScript/V8/SplitProxy/V8IsolateProxyImpl.cs b/ClearScript/V8/SplitProxy/V8IsolateProxyImpl.cs index 96d65b4a8..d8ed6528a 100644 --- a/ClearScript/V8/SplitProxy/V8IsolateProxyImpl.cs +++ b/ClearScript/V8/SplitProxy/V8IsolateProxyImpl.cs @@ -15,68 +15,125 @@ internal sealed class V8IsolateProxyImpl : V8IsolateProxy public V8IsolateProxyImpl(string name, V8RuntimeConstraints constraints, V8RuntimeFlags flags, int debugPort) { - holder = new V8EntityHolder("V8 runtime", () => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_Create( - name, - constraints?.MaxNewSpaceSize ?? -1, - constraints?.MaxOldSpaceSize ?? -1, - constraints?.HeapExpansionMultiplier ?? 0, - constraints?.MaxArrayBufferAllocation ?? ulong.MaxValue, - flags, - debugPort - ))); + holder = new V8EntityHolder("V8 runtime", () => + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_Create( + name, + constraints?.MaxNewSpaceSize ?? -1, + constraints?.MaxOldSpaceSize ?? -1, + constraints?.HeapExpansionMultiplier ?? 0, + constraints?.MaxArrayBufferAllocation ?? ulong.MaxValue, + flags, + debugPort + ); + } + }); } public V8Context.Handle CreateContext(string name, V8ScriptEngineFlags flags, int debugPort) { - return V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CreateContext( - Handle, - name, - flags, - debugPort - )); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_CreateContext( + Handle, + name, + flags, + debugPort + ); + } } #region V8IsolateProxy overrides public override UIntPtr MaxHeapSize { - get => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetMaxHeapSize(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetMaxHeapSize(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetMaxHeapSize(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetMaxHeapSize(Handle, value); + } + } } public override TimeSpan HeapSizeSampleInterval { - get => V8SplitProxyNative.Invoke(instance => TimeSpan.FromMilliseconds(instance.V8Isolate_GetHeapSizeSampleInterval(Handle))); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetHeapSizeSampleInterval(Handle, value.TotalMilliseconds)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return TimeSpan.FromMilliseconds(instance.V8Isolate_GetHeapSizeSampleInterval(Handle)); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetHeapSizeSampleInterval(Handle, value.TotalMilliseconds); + } + } } public override UIntPtr MaxStackUsage { - get => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetMaxStackUsage(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetMaxStackUsage(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetMaxStackUsage(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetMaxStackUsage(Handle, value); + } + } } public override void AwaitDebuggerAndPause() { - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_AwaitDebuggerAndPause(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_AwaitDebuggerAndPause(Handle); + } } public override void CancelAwaitDebugger() { - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CancelAwaitDebugger(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CancelAwaitDebugger(Handle); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code) { - return new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Isolate_Compile( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code - ))); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_Compile( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) @@ -87,21 +144,20 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return Compile(documentInfo, code); } - byte[] tempCacheBytes = null; - var script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CompileProducingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - out tempCacheBytes - ))); - - cacheBytes = tempCacheBytes; - return script; + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileProducingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + out cacheBytes + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) @@ -112,22 +168,21 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return Compile(documentInfo, code); } - var tempCacheAccepted = false; - var script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CompileConsumingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - cacheBytes, - out tempCacheAccepted - ))); - - cacheAccepted = tempCacheAccepted; - return script; + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileConsumingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + cacheBytes, + out cacheAccepted + )); + } } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) @@ -153,21 +208,22 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code return script; } - var tempCacheResult = V8CacheResult.Disabled; - script = new V8ScriptImpl(documentInfo, code.GetDigest(), V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CompileUpdatingCache( - Handle, - MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), - MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), - documentInfo.UniqueId, - documentInfo.Category.Kind, - V8ProxyHelpers.AddRefHostObject(documentInfo), - code, - cacheKind, - ref tempCacheBytes, - out tempCacheResult - ))); - - cacheResult = tempCacheResult; + using (V8SplitProxyNative.Invoke(out var instance)) + { + script = new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileUpdatingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + ref tempCacheBytes, + out cacheResult + )); + } + if (cacheResult == V8CacheResult.Updated) { cacheBytes = tempCacheBytes; @@ -178,14 +234,40 @@ out tempCacheResult public override bool EnableInterruptPropagation { - get => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetEnableInterruptPropagation(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetEnableInterruptPropagation(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetEnableInterruptPropagation(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetEnableInterruptPropagation(Handle, value); + } + } } public override bool DisableHeapSizeViolationInterrupt { - get => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetDisableHeapSizeViolationInterrupt(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetDisableHeapSizeViolationInterrupt(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetDisableHeapSizeViolationInterrupt(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetDisableHeapSizeViolationInterrupt(Handle, value); + } + } } public override V8RuntimeHeapInfo GetHeapInfo() @@ -197,7 +279,11 @@ public override V8RuntimeHeapInfo GetHeapInfo() var usedHeapSize = 0UL; var heapSizeLimit = 0UL; var totalExternalSize = 0UL; - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_GetHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } return new V8RuntimeHeapInfo { @@ -214,18 +300,29 @@ public override V8RuntimeHeapInfo GetHeapInfo() public override V8Runtime.Statistics GetStatistics() { var statistics = new V8Runtime.Statistics(); - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts); + } + return statistics; } public override void CollectGarbage(bool exhaustive) { - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CollectGarbage(Handle, exhaustive)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CollectGarbage(Handle, exhaustive); + } } public override bool BeginCpuProfile(string name, V8CpuProfileFlags flags) { - return V8SplitProxyNative.Invoke(instance => instance.V8Isolate_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection))); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection)); + } } public override V8.V8CpuProfile EndCpuProfile(string name) @@ -235,8 +332,10 @@ public override V8.V8CpuProfile EndCpuProfile(string name) Action action = pProfile => V8CpuProfile.ProcessProfile(Handle, pProfile, profile); using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) { - var pAction = actionScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_EndCpuProfile(Handle, name, pAction)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_EndCpuProfile(Handle, name, actionScope.Value); + } } return profile; @@ -244,21 +343,39 @@ public override V8.V8CpuProfile EndCpuProfile(string name) public override void CollectCpuProfileSample() { - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_CollectCpuProfileSample(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CollectCpuProfileSample(Handle); + } } public override uint CpuProfileSampleInterval { - get => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_GetCpuProfileSampleInterval(Handle)); - set => V8SplitProxyNative.Invoke(instance => instance.V8Isolate_SetCpuProfileSampleInterval(Handle, value)); + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetCpuProfileSampleInterval(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetCpuProfileSampleInterval(Handle, value); + } + } } public override void WriteHeapSnapshot(Stream stream) { using (var streamScope = V8ProxyHelpers.CreateAddRefHostObjectScope(stream)) { - var pStream = streamScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Isolate_WriteHeapSnapshot(Handle, pStream)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_WriteHeapSnapshot(Handle, streamScope.Value); + } } } diff --git a/ClearScript/V8/SplitProxy/V8ObjectImpl.cs b/ClearScript/V8/SplitProxy/V8ObjectImpl.cs index 44c32d973..b0daded49 100644 --- a/ClearScript/V8/SplitProxy/V8ObjectImpl.cs +++ b/ClearScript/V8/SplitProxy/V8ObjectImpl.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -98,60 +98,90 @@ public JavaScriptObjectFlags ObjectFlags public object GetProperty(string name) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_GetNamedProperty(Handle, name)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetNamedProperty(Handle, name); + } } public bool TryGetProperty(string name, out object value) { - object tempValue = null; - var result = V8SplitProxyNative.Invoke(instance => instance.V8Object_TryGetNamedProperty(Handle, name, out tempValue)); - value = tempValue; - return result; + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_TryGetNamedProperty(Handle, name, out value); + } } public void SetProperty(string name, object value) { - V8SplitProxyNative.Invoke(instance => instance.V8Object_SetNamedProperty(Handle, name, value)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_SetNamedProperty(Handle, name, value); + } } public bool DeleteProperty(string name) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_DeleteNamedProperty(Handle, name)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_DeleteNamedProperty(Handle, name); + } } public string[] GetPropertyNames(bool includeIndices) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_GetPropertyNames(Handle, includeIndices)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetPropertyNames(Handle, includeIndices); + } } public object GetProperty(int index) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_GetIndexedProperty(Handle, index)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetIndexedProperty(Handle, index); + } } public void SetProperty(int index, object value) { - V8SplitProxyNative.Invoke(instance => instance.V8Object_SetIndexedProperty(Handle, index, value)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_SetIndexedProperty(Handle, index, value); + } } public bool DeleteProperty(int index) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_DeleteIndexedProperty(Handle, index)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_DeleteIndexedProperty(Handle, index); + } } public int[] GetPropertyIndices() { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_GetPropertyIndices(Handle)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetPropertyIndices(Handle); + } } public object Invoke(bool asConstructor, object[] args) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_Invoke(Handle, asConstructor, args)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_Invoke(Handle, asConstructor, args); + } } public object InvokeMethod(string name, object[] args) { - return V8SplitProxyNative.Invoke(instance => instance.V8Object_InvokeMethod(Handle, name, args)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_InvokeMethod(Handle, name, args); + } } public bool IsPromise => Subtype == V8Value.Subtype.Promise; @@ -247,7 +277,12 @@ public V8ArrayBufferOrViewInfo GetArrayBufferOrViewInfo() var offset = 0UL; var size = 0UL; var length = 0UL; - V8SplitProxyNative.Invoke(instance => instance.V8Object_GetArrayBufferOrViewInfo(Handle, out arrayBuffer, out offset, out size, out length)); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_GetArrayBufferOrViewInfo(Handle, out arrayBuffer, out offset, out size, out length); + } + return new V8ArrayBufferOrViewInfo(kind, arrayBuffer, offset, size, length); } @@ -258,8 +293,10 @@ public void InvokeWithArrayBufferOrViewData(Action action) { using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) { - var pAction = actionScope.Value; - V8SplitProxyNative.Invoke(instance => instance.V8Object_InvokeWithArrayBufferOrViewData(Handle, pAction)); + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_InvokeWithArrayBufferOrViewData(Handle, actionScope.Value); + } } } diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyHelpers.cs b/ClearScript/V8/SplitProxy/V8SplitProxyHelpers.cs index 29d59fbd6..5d6769329 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyHelpers.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyHelpers.cs @@ -12,26 +12,128 @@ namespace Microsoft.ClearScript.V8.SplitProxy { #region native object helpers - internal static class StdString + /// + /// Wraps an std::wstring. + /// + public readonly ref struct StdString { - public static IScope CreateScope(string value = null) + internal readonly Ptr ptr; + private readonly bool owns; + + /// + /// Create a new std::wstring. + /// + /// The contents of the new std::wstring. + public StdString(string value) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdString_New(value ?? string.Empty), instance.StdString_Delete)); + if (value != null) + { + ptr = V8SplitProxyNative.Instance.StdString_New(value); + owns = true; + } + else + { + ptr = Ptr.Null; + owns = false; + } } - public static string GetValue(Ptr pString) + internal StdString(Ptr pValue) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdString_GetValue(pString)); + ptr = pValue; + owns = false; } - public static void SetValue(Ptr pString, string value) + /// + /// Delete the wrapped std::wstring. + /// + public void Dispose() { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdString_SetValue(pString, value)); + if (owns) + { + V8SplitProxyNative.Instance.StdString_Delete(ptr); + } + } + + /// + /// Compare the wrapped std::wstring to a . + /// + /// The string to compare the wrapped std::wstring to. + /// True if the strings are byte for byte equal, false otherwise. + public bool Equals(string other) + { + if (ptr == Ptr.Null) + { + return other == null; + } + else if (other == null) + { + return false; + } + + V8SplitProxyNative.Instance.StdString_GetValue(ptr, out IntPtr value, out int length); + + if (length != other.Length) + { + return false; + } + else if (length == 0) + { + return true; + } + + unsafe + { + char* i = (char*)value; + char* end = i + length; + + fixed (char* otherPtr = other) + { + char* j = otherPtr; + + while (i < end) + { + if (*i != *j) + { + return false; + } + + i++; + j++; + } + } + } + + return true; + } + + /// + /// Create a new string with the contents of the wrapped std::wstring. + /// + /// A new managed string with the same contents as the wrapped std::wtring byte for byte. + public override string ToString() + { + return ptr != Ptr.Null ? GetValue(ptr) : null; + } + + internal static IScope CreateScope(string value = null) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdString_New(value ?? string.Empty), V8SplitProxyNative.Instance.StdString_Delete); + } + + internal static string GetValue(Ptr pString) + { + return V8SplitProxyNative.Instance.StdString_GetValue(pString); + } + + internal static void SetValue(Ptr pString, string value) + { + V8SplitProxyNative.Instance.StdString_SetValue(pString, value); } #region Nested type: Ptr - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -56,59 +158,75 @@ public readonly struct Ptr #endregion } - internal static class StdStringArray + /// + /// Wraps an std::vector<std::wstring>. + /// + public readonly ref struct StdStringArray { - public static IScope CreateScope(int elementCount = 0) + private readonly Ptr ptr; + + internal StdStringArray(Ptr pValue) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdStringArray_New(elementCount), instance.StdStringArray_Delete)); + ptr = pValue; } - public static IScope CreateScope(string[] array) + /// + /// Set the length of the wrapped std::vector<std::wstring>. + /// + /// The new length + public void SetElementCount(int elementCount) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdStringArray_Delete)); + if (ptr != Ptr.Null) + throw new NullReferenceException("StdStringArray is uninitialized"); + + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(ptr, elementCount); } - public static int GetElementCount(Ptr pArray) + internal static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdStringArray_GetElementCount(pArray)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdStringArray_New(elementCount), V8SplitProxyNative.Instance.StdStringArray_Delete); } - public static void SetElementCount(Ptr pArray, int elementCount) + internal static IScope CreateScope(string[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdStringArray_SetElementCount(pArray, elementCount)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdStringArray_Delete); } - public static string[] ToArray(Ptr pArray) + internal static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdStringArray_GetElementCount(pArray); - var array = new string[elementCount]; - - if (elementCount > 0) - { - for (var index = 0; index < elementCount; index++) - { - array[index] = instance.StdStringArray_GetElement(pArray, index); - } - } + return V8SplitProxyNative.Instance.StdStringArray_GetElementCount(pArray); + } - return array; - }); + internal static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(pArray, elementCount); } - public static void CopyFromArray(Ptr pArray, string[] array) + internal static string[] ToArray(Ptr pArray) { - V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = array?.Length ?? 0; - instance.StdStringArray_SetElementCount(pArray, elementCount); + var elementCount = V8SplitProxyNative.Instance.StdStringArray_GetElementCount(pArray); + var array = new string[elementCount]; + if (elementCount > 0) + { for (var index = 0; index < elementCount; index++) { - instance.StdStringArray_SetElement(pArray, index, array[index]); + array[index] = V8SplitProxyNative.Instance.StdStringArray_GetElement(pArray, index); } - }); + } + + return array; + } + + internal static void CopyFromArray(Ptr pArray, string[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(pArray, elementCount); + + for (var index = 0; index < elementCount; index++) + { + V8SplitProxyNative.Instance.StdStringArray_SetElement(pArray, index, array[index]); + } } private static Ptr NewFromArray(IV8SplitProxyNative instance, string[] array) @@ -129,7 +247,7 @@ private static Ptr NewFromArray(IV8SplitProxyNative instance, string[] array) #region Nested type: Ptr - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -158,52 +276,46 @@ internal static class StdByteArray { public static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdByteArray_New(elementCount), instance.StdByteArray_Delete)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdByteArray_New(elementCount), V8SplitProxyNative.Instance.StdByteArray_Delete); } public static IScope CreateScope(byte[] array) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdByteArray_Delete)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdByteArray_Delete); } public static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdByteArray_GetElementCount(pArray)); + return V8SplitProxyNative.Instance.StdByteArray_GetElementCount(pArray); } public static void SetElementCount(Ptr pArray, int elementCount) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdByteArray_SetElementCount(pArray, elementCount)); + V8SplitProxyNative.Instance.StdByteArray_SetElementCount(pArray, elementCount); } public static byte[] ToArray(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdByteArray_GetElementCount(pArray); - var array = new byte[elementCount]; + var elementCount = V8SplitProxyNative.Instance.StdByteArray_GetElementCount(pArray); + var array = new byte[elementCount]; - if (elementCount > 0) - { - Marshal.Copy(instance.StdByteArray_GetData(pArray), array, 0, elementCount); - } + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdByteArray_GetData(pArray), array, 0, elementCount); + } - return array; - }); + return array; } public static void CopyFromArray(Ptr pArray, byte[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = array?.Length ?? 0; - instance.StdByteArray_SetElementCount(pArray, elementCount); + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdByteArray_SetElementCount(pArray, elementCount); - if (elementCount > 0) - { - Marshal.Copy(array, 0, instance.StdByteArray_GetData(pArray), elementCount); - } - }); + if (elementCount > 0) + { + Marshal.Copy(array, 0, V8SplitProxyNative.Instance.StdByteArray_GetData(pArray), elementCount); + } } private static Ptr NewFromArray(IV8SplitProxyNative instance, byte[] array) @@ -246,47 +358,66 @@ public readonly struct Ptr #endregion } - internal static class StdInt32Array + /// + /// Wraps an std::vector<int32_t>. + /// + public readonly ref struct StdInt32Array { - public static IScope CreateScope(int elementCount = 0) + private readonly Ptr ptr; + + internal StdInt32Array(Ptr pValue) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdInt32Array_New(elementCount), instance.StdInt32Array_Delete)); + ptr = pValue; } - public static IScope CreateScope(int[] array) + /// + /// Set the length of the wrapped std::vector<int32_t>. + /// + /// The new length. + public void SetElementCount(int elementCount) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdInt32Array_Delete)); + if (ptr == Ptr.Null) + throw new NullReferenceException("StdInt32Array is uninitialized"); + + V8SplitProxyNative.Instance.StdInt32Array_SetElementCount(ptr, elementCount); } - public static int GetElementCount(Ptr pArray) + internal static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdInt32Array_GetElementCount(pArray)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdInt32Array_New(elementCount), V8SplitProxyNative.Instance.StdInt32Array_Delete); } - public static void SetElementCount(Ptr pArray, int elementCount) + internal static IScope CreateScope(int[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdInt32Array_SetElementCount(pArray, elementCount)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdInt32Array_Delete); } - public static int[] ToArray(Ptr pArray) + internal static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdInt32Array_GetElementCount(pArray); - var array = new int[elementCount]; + return V8SplitProxyNative.Instance.StdInt32Array_GetElementCount(pArray); + } - if (elementCount > 0) - { - Marshal.Copy(instance.StdInt32Array_GetData(pArray), array, 0, elementCount); - } + internal static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdInt32Array_SetElementCount(pArray, elementCount); + } - return array; - }); + internal static int[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdInt32Array_GetElementCount(pArray); + var array = new int[elementCount]; + + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdInt32Array_GetData(pArray), array, 0, elementCount); + } + + return array; } - public static void CopyFromArray(Ptr pArray, int[] array) + internal static void CopyFromArray(Ptr pArray, int[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) { var elementCount = array?.Length ?? 0; instance.StdInt32Array_SetElementCount(pArray, elementCount); @@ -295,7 +426,7 @@ public static void CopyFromArray(Ptr pArray, int[] array) { Marshal.Copy(array, 0, instance.StdInt32Array_GetData(pArray), elementCount); } - }); + }; } private static Ptr NewFromArray(IV8SplitProxyNative instance, int[] array) @@ -313,7 +444,7 @@ private static Ptr NewFromArray(IV8SplitProxyNative instance, int[] array) #region Nested type: Ptr - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -342,52 +473,46 @@ internal static class StdUInt32Array { public static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdUInt32Array_New(elementCount), instance.StdUInt32Array_Delete)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdUInt32Array_New(elementCount), V8SplitProxyNative.Instance.StdUInt32Array_Delete); } public static IScope CreateScope(uint[] array) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdUInt32Array_Delete)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdUInt32Array_Delete); } public static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdUInt32Array_GetElementCount(pArray)); + return V8SplitProxyNative.Instance.StdUInt32Array_GetElementCount(pArray); } public static void SetElementCount(Ptr pArray, int elementCount) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdUInt32Array_SetElementCount(pArray, elementCount)); + V8SplitProxyNative.Instance.StdUInt32Array_SetElementCount(pArray, elementCount); } public static uint[] ToArray(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdUInt32Array_GetElementCount(pArray); - var array = new uint[elementCount]; + var elementCount = V8SplitProxyNative.Instance.StdUInt32Array_GetElementCount(pArray); + var array = new uint[elementCount]; - if (elementCount > 0) - { - UnmanagedMemoryHelpers.Copy(instance.StdUInt32Array_GetData(pArray), (ulong)elementCount, array, 0); - } + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(V8SplitProxyNative.Instance.StdUInt32Array_GetData(pArray), (ulong)elementCount, array, 0); + } - return array; - }); + return array; } public static void CopyFromArray(Ptr pArray, uint[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = array?.Length ?? 0; - instance.StdUInt32Array_SetElementCount(pArray, elementCount); + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdUInt32Array_SetElementCount(pArray, elementCount); - if (elementCount > 0) - { - UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, instance.StdUInt32Array_GetData(pArray)); - } - }); + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, V8SplitProxyNative.Instance.StdUInt32Array_GetData(pArray)); + } } private static Ptr NewFromArray(IV8SplitProxyNative instance, uint[] array) @@ -434,52 +559,46 @@ internal static class StdUInt64Array { public static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdUInt64Array_New(elementCount), instance.StdUInt64Array_Delete)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdUInt64Array_New(elementCount), V8SplitProxyNative.Instance.StdUInt64Array_Delete); } public static IScope CreateScope(ulong[] array) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdUInt64Array_Delete)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdUInt64Array_Delete); } public static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdUInt64Array_GetElementCount(pArray)); + return V8SplitProxyNative.Instance.StdUInt64Array_GetElementCount(pArray); } public static void SetElementCount(Ptr pArray, int elementCount) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdUInt64Array_SetElementCount(pArray, elementCount)); + V8SplitProxyNative.Instance.StdUInt64Array_SetElementCount(pArray, elementCount); } public static ulong[] ToArray(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdUInt64Array_GetElementCount(pArray); - var array = new ulong[elementCount]; + var elementCount = V8SplitProxyNative.Instance.StdUInt64Array_GetElementCount(pArray); + var array = new ulong[elementCount]; - if (elementCount > 0) - { - UnmanagedMemoryHelpers.Copy(instance.StdUInt64Array_GetData(pArray), (ulong)elementCount, array, 0); - } + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(V8SplitProxyNative.Instance.StdUInt64Array_GetData(pArray), (ulong)elementCount, array, 0); + } - return array; - }); + return array; } public static void CopyFromArray(Ptr pArray, ulong[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = array?.Length ?? 0; - instance.StdUInt64Array_SetElementCount(pArray, elementCount); + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdUInt64Array_SetElementCount(pArray, elementCount); - if (elementCount > 0) - { - UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, instance.StdUInt64Array_GetData(pArray)); - } - }); + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, V8SplitProxyNative.Instance.StdUInt64Array_GetData(pArray)); + } } private static Ptr NewFromArray(IV8SplitProxyNative instance, ulong[] array) @@ -526,52 +645,46 @@ internal static class StdPtrArray { public static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdPtrArray_New(elementCount), instance.StdPtrArray_Delete)); + return Scope.Create(() => V8SplitProxyNative.Instance.StdPtrArray_New(elementCount), V8SplitProxyNative.Instance.StdPtrArray_Delete); } public static IScope CreateScope(IntPtr[] array) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdPtrArray_Delete)); + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdPtrArray_Delete); } public static int GetElementCount(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdPtrArray_GetElementCount(pArray)); + return V8SplitProxyNative.Instance.StdPtrArray_GetElementCount(pArray); } public static void SetElementCount(Ptr pArray, int elementCount) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdPtrArray_SetElementCount(pArray, elementCount)); + V8SplitProxyNative.Instance.StdPtrArray_SetElementCount(pArray, elementCount); } public static IntPtr[] ToArray(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = instance.StdPtrArray_GetElementCount(pArray); - var array = new IntPtr[elementCount]; + var elementCount = V8SplitProxyNative.Instance.StdPtrArray_GetElementCount(pArray); + var array = new IntPtr[elementCount]; - if (elementCount > 0) - { - Marshal.Copy(instance.StdPtrArray_GetData(pArray), array, 0, elementCount); - } + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdPtrArray_GetData(pArray), array, 0, elementCount); + } - return array; - }); + return array; } public static void CopyFromArray(Ptr pArray, IntPtr[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => - { - var elementCount = array?.Length ?? 0; - instance.StdPtrArray_SetElementCount(pArray, elementCount); + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdPtrArray_SetElementCount(pArray, elementCount); - if (elementCount > 0) - { - Marshal.Copy(array, 0, instance.StdPtrArray_GetData(pArray), elementCount); - } - }); + if (elementCount > 0) + { + Marshal.Copy(array, 0, V8SplitProxyNative.Instance.StdPtrArray_GetData(pArray), elementCount); + } } private static Ptr NewFromArray(IV8SplitProxyNative instance, IntPtr[] array) @@ -614,51 +727,117 @@ public readonly struct Ptr #endregion } - internal static class StdV8ValueArray + /// + /// Wraps an std::vector<V8Value>. + /// + public readonly ref struct StdV8ValueArray { - public static IScope CreateScope(int elementCount = 0) + internal readonly Ptr ptr; + private readonly V8Value.Ptr data; + private readonly bool owns; + + /// + /// Create a new std::vector<V8Value> of a given length. + /// + /// The length of the new std::vector<V8Value>. + public StdV8ValueArray(int elementCount) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => instance.StdV8ValueArray_New(elementCount), instance.StdV8ValueArray_Delete)); + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + ptr = V8SplitProxyNative.Instance.StdV8ValueArray_New(elementCount); + data = V8SplitProxyNative.Instance.StdV8ValueArray_GetData(ptr); + owns = true; } - public static IScope CreateScope(object[] array) + internal StdV8ValueArray(Ptr pArray) { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(() => NewFromArray(instance, array), instance.StdV8ValueArray_Delete)); + ptr = pArray; + owns = false; + + data = pArray != Ptr.Null + ? V8SplitProxyNative.Instance.StdV8ValueArray_GetData(ptr) : V8Value.Ptr.Null; } - public static int GetElementCount(Ptr pArray) + /// + /// Delete the wrapped std::vector<V8Value>. + /// + public void Dispose() { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.StdV8ValueArray_GetElementCount(pArray)); + if (owns) + { + Ptr ptr = this.ptr; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + } } - public static void SetElementCount(Ptr pArray, int elementCount) + /// + /// Retrieve an element of the wrapped std::vector<V8Value>. + /// + /// The index of the element to retrieve. + /// The element. + public V8Value this[int index] { - V8SplitProxyNative.InvokeNoThrow(instance => instance.StdV8ValueArray_SetElementCount(pArray, elementCount)); + get + { + if (ptr == Ptr.Null) + throw new NullReferenceException("StdV8ValueArray is uninitialized"); + + return new V8Value(GetElementPtr(data, index)); + } } - public static object[] ToArray(Ptr pArray) + internal static IScope CreateScope(int elementCount = 0) { - return V8SplitProxyNative.InvokeNoThrow(instance => + return Scope.Create(() => V8SplitProxyNative.Instance.StdV8ValueArray_New(elementCount), ptr => { - var elementCount = instance.StdV8ValueArray_GetElementCount(pArray); - var array = new object[elementCount]; + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + }); + } - if (elementCount > 0) + internal static IScope CreateScope(object[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), ptr => + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + }); + } + + internal static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdV8ValueArray_GetElementCount(pArray); + } + + internal static void SetElementCount(Ptr pArray, int elementCount) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + internal static object[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdV8ValueArray_GetElementCount(pArray); + var array = new object[elementCount]; + + if (elementCount > 0) + { + var pElements = V8SplitProxyNative.Instance.StdV8ValueArray_GetData(pArray); + for (var index = 0; index < elementCount; index++) { - var pElements = instance.StdV8ValueArray_GetData(pArray); - for (var index = 0; index < elementCount; index++) - { - array[index] = V8Value.Get(GetElementPtr(pElements, index)); - } + array[index] = V8Value.Get(GetElementPtr(pElements, index)); } + } - return array; - }); + return array; } - public static void CopyFromArray(Ptr pArray, object[] array) + internal static void CopyFromArray(Ptr pArray, object[] array) { - V8SplitProxyNative.InvokeNoThrow(instance => + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) { var elementCount = array?.Length ?? 0; instance.StdV8ValueArray_SetElementCount(pArray, elementCount); @@ -671,10 +850,10 @@ public static void CopyFromArray(Ptr pArray, object[] array) V8Value.Set(GetElementPtr(pElements, index), array[index]); } } - }); + }; } - private static Ptr NewFromArray(IV8SplitProxyNative instance, object[] array) + internal static Ptr NewFromArray(IV8SplitProxyNative instance, object[] array) { var elementCount = array?.Length ?? 0; var pArray = instance.StdV8ValueArray_New(elementCount); @@ -688,14 +867,14 @@ private static Ptr NewFromArray(IV8SplitProxyNative instance, object[] array) return pArray; } - public static V8Value.Ptr GetElementPtr(V8Value.Ptr pV8Value, int index) + internal static V8Value.Ptr GetElementPtr(V8Value.Ptr pV8Value, int index) { return (V8Value.Ptr)((IntPtr)pV8Value + index * V8Value.Size); } #region Nested type: Ptr - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -720,23 +899,324 @@ public readonly struct Ptr #endregion } - internal static class V8Value + /// + /// Wraps a V8Value. + /// + public readonly ref struct V8Value { - public const int Size = 16; + internal readonly Ptr ptr; + private readonly bool owns; + + /// + /// Create a new value. + /// + /// + public static V8Value New() + { + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + Ptr ptr = V8SplitProxyNative.Instance.V8Value_New(); + return new V8Value(ptr, true); + } + + internal V8Value(Ptr pValue) : this(pValue, false) { } + + private V8Value(Ptr pValue, bool owns) + { + ptr = pValue; + this.owns = owns; + } - public static IScope CreateScope() + /// + /// Delete the wrapped V8Value. + /// + public void Dispose() { - return V8SplitProxyNative.InvokeNoThrow(instance => Scope.Create(instance.V8Value_New, instance.V8Value_Delete)); + if (owns) + { + Ptr ptr = this.ptr; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_Delete(ptr); + } } - public static IScope CreateScope(object obj) + /// + /// Retrieve the value of the wrapped V8Value. + /// + /// A variant struct that holds a copy of the contents of the wrapped V8Value. + /// + /// If the retrieved value is a , it is your responsibility to + /// dispose of it by calling on it. + /// + public Decoded Decode() + { + Ptr ptr = this.ptr; + + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Value_Decode(ptr, out Decoded decoded); + return decoded; + }; + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public BigInteger GetBigInt() + { + using var decoded = Decode(); + return decoded.GetBigInt(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public bool GetBoolean() + { + using var decoded = Decode(); + return decoded.GetBoolean(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public DateTime GetDateTime() + { + using var decoded = Decode(); + return decoded.GetDateTime(); + } + + /// + /// Decode the value and attempt to obtain a host object from it. + /// + /// The host object value. + public object GetHostObject() + { + using var decoded = Decode(); + return decoded.GetHostObject(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public int GetInt32() + { + using var decoded = Decode(); + return decoded.GetInt32(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public double GetNumber() + { + using var decoded = Decode(); + return decoded.GetNumber(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public string GetString() + { + using var decoded = Decode(); + return decoded.GetString(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public uint GetUInt32() + { + using var decoded = Decode(); + return decoded.GetUInt32(); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetBigInt(BigInteger value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetBigInt(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetBoolean(bool value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetBoolean(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetDateTime(DateTime value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetDateTime(ptr, value); + } + + /// + /// Store a pointer to a host object in the wrapped V8Value as a + /// or . + /// + /// The pointer to store. + /// + /// For best performance, only pass IV8HostObject or InvokeHostObject to JavaScript. + /// + public void SetHostObject(object value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + if (value != null) + SetHostObject(ptr, value); + else + SetNull(ptr); + } + + /// + /// Store an in the wrapped V8Value as a . + /// + /// The value to store. + public void SetInt32(int value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a (nothing, not even null, not even undefined) in the wrapped + /// V8Value as a . Nonexistent is the default value of V8Value. + /// + public void SetNonexistent() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNonexistent(ptr); + } + + /// + /// Store a null in the wrapped V8Value as a . + /// + public void SetNull() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNull(ptr); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetNumber(double value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a or + /// . + /// + /// The value to store. + public void SetString(string value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + if (value != null) + SetString(ptr, value); + else + SetNull(ptr); + } + + /// + /// Store an in the wrapped V8Value as a . + /// + public void SetUndefined() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetUndefined(ptr); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetUInt32(uint value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a JavaScript object in the wrapped V8Value as a . + /// + /// The value to store. + public void SetV8Object(ScriptObject value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + var impl = ((V8ScriptItem)value).Unwrap(); + SetV8Object(ptr, (V8ObjectImpl)impl); + } + + internal const int Size = 16; + + internal static IScope CreateScope() + { + return Scope.Create(() => V8SplitProxyNative.Instance.V8Value_New(), ptr => + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_Delete(ptr); + }); + } + + internal static IScope CreateScope(object obj) { var scope = CreateScope(); Set(scope.Value, obj); return scope; } - public static void Set(Ptr pV8Value, object obj) + internal static void Set(Ptr pV8Value, object obj) { if (obj is Nonexistent) { @@ -895,11 +1375,13 @@ public static void Set(Ptr pV8Value, object obj) SetHostObject(pV8Value, obj); } - public static object Get(Ptr pV8Value) + internal static object Get(Ptr pV8Value) { - var decoded = default(Decoded); - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_Decode(pV8Value, out decoded)); - return decoded.Get(); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Value_Decode(pV8Value, out Decoded decoded); + return decoded.Get(); + } } private static bool TryGetBigInteger(int signBit, int wordCount, IntPtr pWords, out BigInteger result) @@ -931,47 +1413,56 @@ private static bool TryGetBigInteger(int signBit, int wordCount, IntPtr pWords, private static void SetNonexistent(Ptr pV8Value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetNonexistent(pV8Value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNonexistent(pV8Value); } private static void SetUndefined(Ptr pV8Value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetUndefined(pV8Value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetUndefined(pV8Value); } private static void SetNull(Ptr pV8Value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetNull(pV8Value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNull(pV8Value); } private static void SetBoolean(Ptr pV8Value, bool value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetBoolean(pV8Value, value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetBoolean(pV8Value, value); } private static void SetNumeric(Ptr pV8Value, double value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetNumber(pV8Value, value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNumber(pV8Value, value); } private static void SetNumeric(Ptr pV8Value, int value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetInt32(pV8Value, value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetInt32(pV8Value, value); } private static void SetNumeric(Ptr pV8Value, uint value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetUInt32(pV8Value, value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetUInt32(pV8Value, value); } private static void SetString(Ptr pV8Value, string value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetString(pV8Value, value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetString(pV8Value, value); } private static void SetDateTime(Ptr pV8Value, DateTime value) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetDateTime(pV8Value, (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetDateTime(pV8Value, (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds); } private static void SetBigInt(Ptr pV8Value, BigInteger value) @@ -984,35 +1475,90 @@ private static void SetBigInt(Ptr pV8Value, BigInteger value) } var bytes = value.ToByteArray(); - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetBigInt(pV8Value, signBit, bytes)); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetBigInt(pV8Value, signBit, bytes); } private static void SetV8Object(Ptr pV8Value, V8ObjectImpl v8ObjectImpl) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetV8Object(pV8Value, v8ObjectImpl.Handle, v8ObjectImpl.Subtype, v8ObjectImpl.Flags)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetV8Object(pV8Value, v8ObjectImpl.Handle, v8ObjectImpl.Subtype, v8ObjectImpl.Flags); } private static void SetHostObject(Ptr pV8Value, object obj) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Value_SetHostObject(pV8Value, V8ProxyHelpers.AddRefHostObject(obj))); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetHostObject(pV8Value, V8ProxyHelpers.AddRefHostObject(obj)); } #region Nested type: Type + /// + /// The type of the wrapped V8Value. + /// public enum Type : byte { // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Type + + /// + /// . This is the default value of V8Value. + /// Nonexistent, + + /// + /// Returned by JavaScript when a property does not exist. + /// Undefined, + + /// + /// An untyped null. + /// Null, + + /// + /// . + /// Boolean, + + /// + /// . + /// Number, + + /// + /// . + /// Int32, + + /// + /// . + /// UInt32, + + /// + /// . + /// String, + + /// + /// . + /// DateTime, + + /// + /// . + /// BigInt, + + /// + /// A JavaScript object. + /// V8Object, + + /// + /// A host object. + /// HostObject } @@ -1020,26 +1566,101 @@ public enum Type : byte #region Nested type: Subtype + /// + /// If the wrapped V8Value is a , what kind of object it is. + /// public enum Subtype : byte { // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Subtype + + /// + /// A regular JavaScript object. + /// None, + + /// + /// A function. + /// Function, + + /// + /// An iterator. + /// Iterator, + + /// + /// A promise. + /// Promise, + + /// + /// An array of JavaScript objects. + /// Array, + + /// + /// An array buffer. + /// ArrayBuffer, + + /// + /// A data view. + /// DataView, + + /// + /// An array of . + /// Uint8Array, + + /// + /// An array of . + /// Uint8ClampedArray, + + /// + /// A array of . + /// Int8Array, + + /// + /// A array of . + /// Uint16Array, + + /// + /// An array of . + /// Int16Array, + + /// + /// An array of . + /// Uint32Array, + + /// + /// An array of . + /// Int32Array, + + /// + /// An array of . + /// BigUint64Array, + + /// + /// An array of . + /// BigInt64Array, + + /// + /// An array of . + /// Float32Array, + + /// + /// An array of . + /// Float64Array } @@ -1047,13 +1668,33 @@ public enum Subtype : byte #region Nested type: Flags + /// + /// If the wrapped V8Value is a , additional information about it. + /// [Flags] public enum Flags : ushort { // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Flags + + /// + /// No special meaning. + /// None = 0, + + /// + /// If the object is shared between something, I don't know. + /// Shared = 0x0001, + + /// + /// If the wrapped V8Value is a , if it's async. + /// Async = 0x0002, + + /// + /// If thewrapped V8Value is a , if it's a generator (contains + /// yield statements). + /// Generator = 0x0004 } @@ -1061,7 +1702,7 @@ public enum Flags : ushort #region Nested type: Ptr - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -1087,22 +1728,264 @@ public readonly struct Ptr #region Nested type: Decoded + /// + /// A variant struct that contains the value retrieved from a . + /// [StructLayout(LayoutKind.Explicit)] - public struct Decoded + public struct Decoded : IDisposable { // IMPORTANT: maintain bitwise equivalence with native struct V8Value::Decoded + + /// + /// The type of the value. + /// [FieldOffset(0)] public Type Type; + + /// + /// If the value is a , what kind of object it is. + /// [FieldOffset(1)] public Subtype Subtype; + + /// + /// If the value is a , additional information about it. + /// [FieldOffset(2)] public Flags Flags; + + /// + /// If the value is a , if it's negative. + /// [FieldOffset(2)] public short SignBit; + + /// + /// If the value is a or a , how long it + /// is. + /// [FieldOffset(4)] public int Length; + + /// + /// If the value is a pointer to a , the object's identity hash. + /// [FieldOffset(4)] public int IdentityHash; + + /// + /// If the value is a , its value. + /// [FieldOffset(8)] public int Int32Value; + + /// + /// If the value is a , its value. + /// [FieldOffset(8)] public uint UInt32Value; + + /// + /// If the value is a , its value. + /// [FieldOffset(8)] public double DoubleValue; + + /// + /// If the value is a or a , + /// pointer to it. + /// [FieldOffset(8)] public IntPtr PtrOrHandle; - public object Get() + /// + /// If the value is a , we must dispose of it when we're done. + /// + public void Dispose() + { + if (Type == Type.V8Object) + { + Type = Type.Nonexistent; + var hEntity = (V8Entity.Handle)PtrOrHandle; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Entity_DestroyHandle(hEntity); + } + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a + /// If the value is not a . + /// If the big integer is more than two gigabytes in size. + public readonly BigInteger GetBigInt() + { + if (Type != Type.BigInt) + throw new InvalidCastException($"Tried to get a BigInt out of a {GetTypeName()}"); + + if (!TryGetBigInteger(SignBit, Length, PtrOrHandle, out var result)) + throw new NotSupportedException("The size of the big integer exceeds two gigabytes"); + + return result; + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a . + /// If the value is not a . + public readonly bool GetBoolean() + { + if (Type != Type.Boolean) + throw new InvalidCastException($"Tried to get a Boolean out of a {GetTypeName()}"); + + return Int32Value != 0; + } + + /// + /// Chech that the value is a and return it as a + /// . + /// + /// The value as a . + /// + /// The must have been created with the + /// flag set for this method to + /// work. Else, the Date object will be passed from JavaScript as a + /// . + /// + public readonly DateTime GetDateTime() + { + if (Type != Type.DateTime) + throw new InvalidCastException($"Tried to get a DateTime out of a {GetTypeName()}"); + + return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) + + TimeSpan.FromMilliseconds(DoubleValue); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a . + /// If the value is not a . + public readonly double GetNumber() + { + if (Type != Type.Number) + throw new InvalidCastException($"Tried to get a Double out of a {GetTypeName()}"); + + return DoubleValue; + } + + /// + /// Check that the value is a pointer to a and return it as an + /// . + /// + /// The pointer as an . + /// If the value is not a . + public readonly object GetHostObject() + { + if (Type != Type.HostObject) + throw new InvalidCastException($"Tried to get a host object out of a {GetTypeName()}"); + + return V8ProxyHelpers.GetHostObject(PtrOrHandle); + } + + /// + /// Check that the value is a and return it as an + /// . + /// + /// The value as an . + /// If the value is not a . + public readonly int GetInt32() + { + if (Type != Type.Int32) + throw new InvalidCastException($"Tried to get an Int32 out of a {GetTypeName()}"); + + return Int32Value; + } + + /// + /// Check that the value is a and return a + /// that wraps it. + /// + /// The pointer to the wrapped in a . + /// The value is not a pointer to a . + public readonly V8Object GetV8Object() + { + if (Type != Type.V8Object) + throw new InvalidCastException($"Tried to get a JavaScript object out of a {GetTypeName()}"); + + return new V8Object((V8Object.Handle)PtrOrHandle, IdentityHash); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value decoded as a . + /// If the value is not a . + public readonly string GetString() + { + if (Type != Type.String) + throw new InvalidCastException($"Tried to get a String out of a {GetTypeName()}"); + + return Marshal.PtrToStringUni(PtrOrHandle, Length); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value decoded as a . + /// If the value is not a . + public readonly uint GetUInt32() + { + if (Type != Type.UInt32) + throw new InvalidCastException($"Tried to get a UInt32 out of a {GetTypeName()}"); + + return UInt32Value; + } + + /// + /// Check that the value is a pointer to and return a + /// that wraps it. + /// + /// The pointer to the wrapped in a . + /// If the value is not a pointer to a . + public readonly Uint8Array GetUint8Array() + { + if (Type != Type.V8Object || Subtype != Subtype.Uint8Array) + throw new InvalidCastException( + $"Tried to get a Uint8Array out of a {GetTypeName()}"); + + return new Uint8Array((V8Object.Handle)PtrOrHandle); + } + + /// + /// Return a string describing the type of the value. + /// + /// A string describing the type of the value. + public readonly string GetTypeName() + { + return Type != Type.V8Object || Subtype == Subtype.None + ? Type.ToString() : Subtype.ToString(); + } + + /// + /// Returns a string representing the value and the type of the value. + /// + /// A string representing the value and the type of the value. + public override string ToString() => Type switch + { + Type.Nonexistent => "void (Nonexistent)", + Type.Undefined => "undefined (Undefined)", + Type.Null => "null (Null)", + Type.Boolean => Int32Value != 0 ? "True (Boolean)" : "False (Boolean)", + Type.Number => $"{DoubleValue} (Number)", + Type.Int32 => $"{Int32Value} (Int32)", + Type.UInt32 => $"{UInt32Value} (UInt32)", + Type.String => $"\"{Marshal.PtrToStringUni(PtrOrHandle, Length)}\" (String)", + Type.DateTime => $"{new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) + TimeSpan.FromMilliseconds(DoubleValue)} (DateTime)", + Type.BigInt => $"{(TryGetBigInteger(SignBit, Length, PtrOrHandle, out var bigInt) ? bigInt.ToString() : "null")} (BigInt)", + Type.V8Object => $"0x{PtrOrHandle:x} ({Subtype})", + Type.HostObject => $"0x{PtrOrHandle:x} (HostObject)", + _ => $"unknown ({Type})" + }; + + internal readonly object Get() { switch (Type) { @@ -1144,12 +2027,12 @@ public object Get() } } - public static unsafe object Get(Ptr pValues, int index) + internal static unsafe object Get(Ptr pValues, int index) { return ((Decoded*)(IntPtr)pValues + index)->Get(); } - public static object[] ToArray(int count, Ptr pValues) + internal static object[] ToArray(int count, Ptr pValues) { var array = new object[count]; @@ -1164,7 +2047,7 @@ public static object[] ToArray(int count, Ptr pValues) #region Nested type: Ptr // ReSharper disable once MemberHidesStaticFromOuterClass - public readonly struct Ptr + internal readonly struct Ptr { private readonly IntPtr bits; @@ -1201,7 +2084,9 @@ public static void ProcessProfile(V8Entity.Handle hEntity, Ptr pProfile, V8.V8Cp var endTimestamp = 0UL; var sampleCount = 0; var pRootNode = Node.Ptr.Null; - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8CpuProfile_GetInfo(pProfile, hEntity, out name, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode)); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8CpuProfile_GetInfo(pProfile, hEntity, out name, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); profile.Name = name; profile.StartTimestamp = startTimestamp; @@ -1221,7 +2106,11 @@ public static void ProcessProfile(V8Entity.Handle hEntity, Ptr pProfile, V8.V8Cp var nodeId = 0UL; var timestamp = 0UL; var sampleIndex = index; - var found = V8SplitProxyNative.InvokeNoThrow(instance => instance.V8CpuProfile_GetSample(pProfile, sampleIndex, out nodeId, out timestamp)); + bool found; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + found = instance.V8CpuProfile_GetSample(pProfile, sampleIndex, out nodeId, out timestamp); + if (found) { var node = profile.FindNode(nodeId); @@ -1251,7 +2140,9 @@ private static V8.V8CpuProfile.Node CreateNode(V8Entity.Handle hEntity, Node.Ptr var hitCount = 0UL; var hitLineCount = 0U; var childCount = 0; - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, out scriptName, out functionName, out bailoutReason, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount)); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, out scriptName, out functionName, out bailoutReason, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); var node = new V8.V8CpuProfile.Node { @@ -1269,7 +2160,12 @@ private static V8.V8CpuProfile.Node CreateNode(V8Entity.Handle hEntity, Node.Ptr { int[] lineNumbers = null; uint[] hitCounts = null; - if (V8SplitProxyNative.InvokeNoThrow(instance => instance.V8CpuProfileNode_GetHitLines(pNode, out lineNumbers, out hitCounts))) + bool found; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + found = instance.V8CpuProfileNode_GetHitLines(pNode, out lineNumbers, out hitCounts); + + if (found) { var actualHitLineCount = Math.Min(lineNumbers.Length, hitCounts.Length); if (actualHitLineCount > 0) @@ -1294,7 +2190,11 @@ private static V8.V8CpuProfile.Node CreateNode(V8Entity.Handle hEntity, Node.Ptr for (var index = 0; index < childCount; index++) { var childIndex = index; - var pChildNode = V8SplitProxyNative.InvokeNoThrow(instance => instance.V8CpuProfileNode_GetChildNode(pNode, childIndex)); + Node.Ptr pChildNode; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + pChildNode = instance.V8CpuProfileNode_GetChildNode(pNode, childIndex); + if (pChildNode != Node.Ptr.Null) { childNodes.Add(CreateNode(hEntity, pChildNode)); @@ -1468,11 +2368,148 @@ public readonly struct Handle #endregion } - internal static class V8Object + /// + /// Wraps a JavaScript object. + /// + public readonly ref struct V8Object { + internal readonly Handle ptr; + private readonly int identityHash; + + internal V8Object(Handle hObject, int identityHash) + { + if (hObject == Handle.Empty) + throw new ArgumentNullException(nameof(hObject)); + + ptr = hObject; + this.identityHash = identityHash; + } + + /// + /// Obtain a thin wrapper around a JavaScript object wrapped by a . + /// + /// A wrapper around a JavaScript object. + /// + /// The common case is to pass to this constructor. + /// + public V8Object(ScriptObject scriptObject) + { + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + object target = ((V8ScriptItem)scriptObject).Unwrap(); + var impl = (V8ObjectImpl)target; + ptr = impl.Handle; + identityHash = impl.IdentityHash; + } + + /// + /// Return the identity hash of the JavaScript object. + /// + /// The identity hash of the JavaScript object. + public override int GetHashCode() + { + return identityHash; + } + + /// + /// Obtain the value of a named property of the wrapped JavaScript object. + /// + /// The name of the property. + /// The value of the property will be written here. + public void GetNamedProperty(StdString name, V8Value value) + { + Handle hObject = ptr; + StdString.Ptr pName = name.ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pName == StdString.Ptr.Null) + throw new ArgumentNullException(nameof(name)); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetNamedProperty(hObject, pName, pValue); + } + + /// + /// Obtain the value of a named property of the wrapped JavaScript object. + /// + /// The name of the property. + /// The value of the property will be written here. + public void GetNamedProperty(string name, V8Value value) + { + Handle hObject = ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (name == null) + throw new ArgumentNullException(nameof(name)); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using var stdName = new StdString(name); + StdString.Ptr pName = stdName.ptr; + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetNamedProperty(hObject, pName, pValue); + } + + /// + /// Obtain the value of an indexed property of the wrapped JavaScript object. + /// + /// The index of the property. + /// The value of the property will be written here. + public void GetIndexedProperty(int index, V8Value value) + { + Handle hObject = ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetIndexedProperty(hObject, index, pValue); + } + + /// + /// Invoke the wrapped JavaScript object as a function. + /// + /// The arguments to pass to the function. + /// The return value of the function will be written here. + /// Call the JavaScript as a constructor? + public void Invoke(StdV8ValueArray args, V8Value result, bool asConstructor = false) + { + Handle hObject = ptr; + StdV8ValueArray.Ptr pArgs = args.ptr; + V8Value.Ptr pResult = result.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pArgs == StdV8ValueArray.Ptr.Null) + throw new ArgumentNullException(nameof(args)); + + if (pResult == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(result)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + #region Nested type: Handle - public readonly struct Handle + internal readonly struct Handle { private readonly IntPtr guts; diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyManaged.cs b/ClearScript/V8/SplitProxy/V8SplitProxyManaged.cs index a21b1f21f..5b1fcf174 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyManaged.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyManaged.cs @@ -35,12 +35,18 @@ public static void Teardown() private static void ScheduleHostException(IntPtr pObject, Exception exception) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.HostException_Schedule(exception.GetBaseException().Message, V8ProxyHelpers.MarshalExceptionToScript(pObject, exception))); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.HostException_Schedule(exception.GetBaseException().Message, V8ProxyHelpers.MarshalExceptionToScript(pObject, exception)); + } } private static void ScheduleHostException(Exception exception) { - V8SplitProxyNative.InvokeNoThrow(instance => instance.HostException_Schedule(exception.GetBaseException().Message, ScriptEngine.Current?.MarshalToScript(exception))); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.HostException_Schedule(exception.GetBaseException().Message, ScriptEngine.Current?.MarshalToScript(exception)); + } } private static uint GetMaxCacheSizeForCategory(DocumentCategory category) @@ -506,7 +512,8 @@ private static void InvokeHostAction(IntPtr pAction) { try { - V8ProxyHelpers.GetHostObject(pAction)(); + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(); } catch (Exception exception) { @@ -518,7 +525,8 @@ private static void ProcessArrayBufferOrViewData(IntPtr pData, IntPtr pAction) { try { - V8ProxyHelpers.GetHostObject>(pAction)(pData); + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(pData); } catch (Exception exception) { @@ -530,7 +538,8 @@ private static void ProcessCpuProfile(V8CpuProfile.Ptr pProfile, IntPtr pAction) { try { - V8ProxyHelpers.GetHostObject>(pAction)(pProfile); + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(pProfile); } catch (Exception exception) { @@ -545,38 +554,51 @@ private static IntPtr CreateV8ObjectCache() private static void CacheV8Object(IntPtr pCache, IntPtr pObject, IntPtr pV8Object) { - V8ProxyHelpers.GetHostObject>(pCache).Add(V8ProxyHelpers.GetHostObject(pObject), pV8Object); + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + ((Dictionary)cache).Add(key, pV8Object); } private static IntPtr GetCachedV8Object(IntPtr pCache, IntPtr pObject) { - return V8ProxyHelpers.GetHostObject>(pCache).TryGetValue(V8ProxyHelpers.GetHostObject(pObject), out IntPtr pV8Object) ? pV8Object : IntPtr.Zero; + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + return ((Dictionary)cache).TryGetValue(key, out IntPtr pV8Object) ? pV8Object : IntPtr.Zero; } private static void GetAllCachedV8Objects(IntPtr pCache, StdPtrArray.Ptr pV8ObjectPtrs) { - var cache = V8ProxyHelpers.GetHostObject>(pCache); - StdPtrArray.CopyFromArray(pV8ObjectPtrs, cache.Values.ToArray()); + object cache = V8ProxyHelpers.GetHostObject(pCache); + StdPtrArray.CopyFromArray(pV8ObjectPtrs, ((Dictionary)cache).Values.ToArray()); } private static bool RemoveV8ObjectCacheEntry(IntPtr pCache, IntPtr pObject) { - return V8ProxyHelpers.GetHostObject>(pCache).Remove(V8ProxyHelpers.GetHostObject(pObject)); + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + return ((Dictionary)cache).Remove(key); } private static IntPtr CreateDebugAgent(StdString.Ptr pName, StdString.Ptr pVersion, int port, bool remote, V8DebugCallback.Handle hCallback) { - return V8ProxyHelpers.AddRefHostObject(new V8DebugAgent(StdString.GetValue(pName), StdString.GetValue(pVersion), port, remote, new V8DebugListenerImpl(hCallback))); + string name = StdString.GetValue(pName); + string version = StdString.GetValue(pVersion); + IV8DebugListener listener = new V8DebugListenerImpl(hCallback); + V8DebugAgent agent = new V8DebugAgent(name, version, port, remote, listener); + return V8ProxyHelpers.AddRefHostObject(agent); } private static void SendDebugMessage(IntPtr pAgent, StdString.Ptr pContent) { - V8ProxyHelpers.GetHostObject(pAgent).SendMessage(StdString.GetValue(pContent)); + object agent = V8ProxyHelpers.GetHostObject(pAgent); + string content = StdString.GetValue(pContent); + ((V8DebugAgent)agent).SendMessage(content); } private static void DestroyDebugAgent(IntPtr pAgent) { - V8ProxyHelpers.GetHostObject(pAgent).Dispose(); + object agent = V8ProxyHelpers.GetHostObject(pAgent); + ((V8DebugAgent)agent).Dispose(); V8ProxyHelpers.ReleaseHostObject(pAgent); } @@ -592,19 +614,32 @@ private static uint GetMaxModuleCacheSize() private static IntPtr AddRefHostObject(IntPtr pObject) { - return V8ProxyHelpers.AddRefHostObject(pObject); + object obj = V8ProxyHelpers.GetHostObject(pObject); + return V8ProxyHelpers.AddRefHostObject(obj); } private static void ReleaseHostObject(IntPtr pObject) { - V8ProxyHelpers.ReleaseHostObject(pObject); + GCHandle handle = GCHandle.FromIntPtr(pObject); + handle.Free(); } private static Invocability GetHostObjectInvocability(IntPtr pObject) { try { - return V8ProxyHelpers.GetHostObjectInvocability(pObject); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is InvokeHostObject) + { + return Invocability.Delegate; + } + else +#endif + { + return V8ProxyHelpers.GetHostObjectInvocability(obj); + } } catch (Exception exception) { @@ -617,7 +652,21 @@ private static void GetHostObjectNamedProperty(IntPtr pObject, StdString.Ptr pNa { try { - V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(pObject, StdString.GetValue(pName))); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + var value = new V8Value(pValue); + hostObject.GetNamedProperty(name, value, out _); + } + else +#endif + { + string name = StdString.GetValue(pName); + V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(obj, name)); + } } catch (Exception exception) { @@ -629,7 +678,21 @@ private static void GetHostObjectNamedPropertyWithCacheability(IntPtr pObject, S { try { - V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(pObject, StdString.GetValue(pName), out isCacheable)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + var value = new V8Value(pValue); + hostObject.GetNamedProperty(name, value, out isCacheable); + } + else +#endif + { + string name = StdString.GetValue(pName); + V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(obj, name, out isCacheable)); + } } catch (Exception exception) { @@ -642,7 +705,28 @@ private static void SetHostObjectNamedProperty(IntPtr pObject, StdString.Ptr pNa { try { - V8ProxyHelpers.SetHostObjectProperty(pObject, StdString.GetValue(pName), V8Value.Decoded.Get(pValue, 0)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + var name = new StdString(pName); + + using (var value = *(V8Value.Decoded*)(IntPtr)pValue) + { + hostObject.SetNamedProperty(name, value); + } + } + } + else +#endif + { + string name = StdString.GetValue(pName); + object value = V8Value.Decoded.Get(pValue, 0); + V8ProxyHelpers.SetHostObjectProperty(obj, name, value); + } } catch (Exception exception) { @@ -654,7 +738,20 @@ private static bool DeleteHostObjectNamedProperty(IntPtr pObject, StdString.Ptr { try { - return V8ProxyHelpers.DeleteHostObjectProperty(pObject, StdString.GetValue(pName)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + return hostObject.DeleteNamedProperty(name); + } + else +#endif + { + string name = StdString.GetValue(pName); + return V8ProxyHelpers.DeleteHostObjectProperty(obj, name); + } } catch (Exception exception) { @@ -665,25 +762,47 @@ private static bool DeleteHostObjectNamedProperty(IntPtr pObject, StdString.Ptr private static void GetHostObjectPropertyNames(IntPtr pObject, StdStringArray.Ptr pNames) { - string[] names; try { - names = V8ProxyHelpers.GetHostObjectPropertyNames(pObject); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var names = new StdStringArray(pNames); + hostObject.GetNamedPropertyNames(names); + } + else +#endif + { + string[] names = V8ProxyHelpers.GetHostObjectPropertyNames(obj); + StdStringArray.CopyFromArray(pNames, names); + } } catch (Exception exception) { ScheduleHostException(pObject, exception); - return; } - - StdStringArray.CopyFromArray(pNames, names); } private static void GetHostObjectIndexedProperty(IntPtr pObject, int index, V8Value.Ptr pValue) { try { - V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(pObject, index)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var value = new V8Value(pValue); + hostObject.GetIndexedProperty(index, value); + } + else +#endif + { + object value = V8ProxyHelpers.GetHostObjectProperty(obj, index); + V8Value.Set(pValue, value); + } } catch (Exception exception) { @@ -695,7 +814,25 @@ private static void SetHostObjectIndexedProperty(IntPtr pObject, int index, V8Va { try { - V8ProxyHelpers.SetHostObjectProperty(pObject, index, V8Value.Decoded.Get(pValue, 0)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + using (var value = *(V8Value.Decoded*)(IntPtr)pValue) + { + hostObject.SetIndexedProperty(index, value); + } + } + } + else +#endif + { + object value = V8Value.Decoded.Get(pValue, 0); + V8ProxyHelpers.SetHostObjectProperty(obj, index, value); + } } catch (Exception exception) { @@ -707,7 +844,18 @@ private static bool DeleteHostObjectIndexedProperty(IntPtr pObject, int index) { try { - return V8ProxyHelpers.DeleteHostObjectProperty(pObject, index); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + return hostObject.DeleteIndexedProperty(index); + } + else +#endif + { + return V8ProxyHelpers.DeleteHostObjectProperty(obj, index); + } } catch (Exception exception) { @@ -718,25 +866,63 @@ private static bool DeleteHostObjectIndexedProperty(IntPtr pObject, int index) private static void GetHostObjectPropertyIndices(IntPtr pObject, StdInt32Array.Ptr pIndices) { - int[] indices; try { - indices = V8ProxyHelpers.GetHostObjectPropertyIndices(pObject); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var indices = new StdInt32Array(pIndices); + hostObject.GetIndexedPropertyIndices(indices); + } + else +#endif + { + int[] indices = V8ProxyHelpers.GetHostObjectPropertyIndices(obj); + StdInt32Array.CopyFromArray(pIndices, indices); + } } catch (Exception exception) { ScheduleHostException(pObject, exception); - return; } - - StdInt32Array.CopyFromArray(pIndices, indices); } private static void InvokeHostObject(IntPtr pObject, bool asConstructor, int argCount, V8Value.Decoded.Ptr pArgs, V8Value.Ptr pResult) { try { - V8Value.Set(pResult, V8ProxyHelpers.InvokeHostObject(pObject, asConstructor, V8Value.Decoded.ToArray(argCount, pArgs))); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is InvokeHostObject method) + { + unsafe + { + var args = new ReadOnlySpan((V8Value.Decoded*)(IntPtr)pArgs, argCount); + var result = new V8Value(pResult); + + try + { + method(args, result); + } + finally + { + for (int i = 0; i < argCount; i++) + { + args[i].Dispose(); + } + } + } + } + else +#endif + { + object[] args = V8Value.Decoded.ToArray(argCount, pArgs); + object result = V8ProxyHelpers.InvokeHostObject(obj, asConstructor, args); + V8Value.Set(pResult, result); + } } catch (Exception exception) { @@ -748,7 +934,38 @@ private static void InvokeHostObjectMethod(IntPtr pObject, StdString.Ptr pName, { try { - V8Value.Set(pResult, V8ProxyHelpers.InvokeHostObjectMethod(pObject, StdString.GetValue(pName), V8Value.Decoded.ToArray(argCount, pArgs))); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + var name = new StdString(pName); + var args = new ReadOnlySpan((V8Value.Decoded*)(IntPtr)pArgs, argCount); + var result = new V8Value(pResult); + + try + { + hostObject.InvokeMethod(name, args, result); + } + finally + { + for (int i = 0; i < argCount; i++) + { + args[i].Dispose(); + } + } + } + } + else +#endif + { + string name = StdString.GetValue(pName); + object[] args = V8Value.Decoded.ToArray(argCount, pArgs); + object result = V8ProxyHelpers.InvokeHostObjectMethod(obj, name, args); + V8Value.Set(pResult, result); + } } catch (Exception exception) { @@ -760,7 +977,20 @@ private static void GetHostObjectEnumerator(IntPtr pObject, V8Value.Ptr pResult) { try { - V8Value.Set(pResult, V8ProxyHelpers.GetHostObjectEnumerator(pObject)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var result = new V8Value(pResult); + hostObject.GetEnumerator(result); + } + else +#endif + { + object result = V8ProxyHelpers.GetHostObjectEnumerator(obj); + V8Value.Set(pResult, result); + } } catch (Exception exception) { @@ -772,7 +1002,20 @@ private static void GetHostObjectAsyncEnumerator(IntPtr pObject, V8Value.Ptr pRe { try { - V8Value.Set(pResult, V8ProxyHelpers.GetHostObjectAsyncEnumerator(pObject)); + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var result = new V8Value(pResult); + hostObject.GetAsyncEnumerator(result); + } + else +#endif + { + object result = V8ProxyHelpers.GetHostObjectAsyncEnumerator(obj); + V8Value.Set(pResult, result); + } } catch (Exception exception) { @@ -858,9 +1101,19 @@ private static void WriteBytesToStream(IntPtr pStream, IntPtr pBytes, int count) { try { + Stream stream = V8ProxyHelpers.GetHostObject(pStream); + +#if NETCOREAPP || NETSTANDARD + unsafe + { + var bytes = new ReadOnlySpan((byte*)pBytes, count); + stream.Write(bytes); + } +#else var bytes = new byte[count]; Marshal.Copy(pBytes, bytes, 0, count); - V8ProxyHelpers.GetHostObject(pStream).Write(bytes, 0, count); + stream.Write(bytes, 0, count); +#endif } catch (Exception exception) { diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt index 18e1c4e01..0225d3679 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt @@ -90,6 +90,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -742,6 +747,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -939,6 +949,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -994,6 +1009,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -1028,6 +1048,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -1052,6 +1077,11 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs index d578dba3c..f9358e6da 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs @@ -4,6 +4,11 @@ + + + + + // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. @@ -19,79 +24,95 @@ private static IV8SplitProxyNative CreateInstance() var architecture = RuntimeInformation.ProcessArchitecture; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + if (architecture == Architecture.X86) { return new Impl_Windows_X86(); } + if (architecture == Architecture.X64) { return new Impl_Windows_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_Windows_Arm64(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { + if (architecture == Architecture.X64) { return new Impl_Linux_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_Linux_Arm64(); } + if (architecture == Architecture.Arm) { return new Impl_Linux_Arm(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { + if (architecture == Architecture.X64) { return new Impl_OSX_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_OSX_Arm64(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + throw new PlatformNotSupportedException("Unsupported operating system"); } + #region Nested type: Impl_Windows_X86 private sealed class Impl_Windows_X86 : IV8SplitProxyNative @@ -132,6 +153,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -784,6 +810,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -981,6 +1012,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -1036,6 +1072,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -1070,6 +1111,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -1094,6 +1140,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -2225,6 +2276,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_X64 private sealed class Impl_Windows_X64 : IV8SplitProxyNative @@ -2265,6 +2317,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -2917,6 +2974,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -3114,6 +3176,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -3169,6 +3236,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -3203,6 +3275,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -3227,6 +3304,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -4358,6 +4440,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_Arm64 private sealed class Impl_Windows_Arm64 : IV8SplitProxyNative @@ -4398,6 +4481,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -5050,6 +5138,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -5247,6 +5340,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -5302,6 +5400,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -5336,6 +5439,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -5360,6 +5468,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -6491,6 +6604,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_X64 private sealed class Impl_Linux_X64 : IV8SplitProxyNative @@ -6531,6 +6645,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -7183,6 +7302,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -7380,6 +7504,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -7435,6 +7564,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -7469,6 +7603,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -7493,6 +7632,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -8624,6 +8768,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_Arm64 private sealed class Impl_Linux_Arm64 : IV8SplitProxyNative @@ -8664,6 +8809,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -9316,6 +9466,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -9513,6 +9668,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -9568,6 +9728,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -9602,6 +9767,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -9626,6 +9796,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -10757,6 +10932,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_Arm private sealed class Impl_Linux_Arm : IV8SplitProxyNative @@ -10797,6 +10973,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -11449,6 +11630,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -11646,6 +11832,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -11701,6 +11892,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -11735,6 +11931,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -11759,6 +11960,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -12890,6 +13096,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_OSX_X64 private sealed class Impl_OSX_X64 : IV8SplitProxyNative @@ -12930,6 +13137,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -13582,6 +13794,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -13779,6 +13996,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -13834,6 +14056,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -13868,6 +14095,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -13892,6 +14124,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -15023,6 +15260,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_OSX_Arm64 private sealed class Impl_OSX_Arm64 : IV8SplitProxyNative @@ -15063,6 +15301,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -15715,6 +15958,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -15912,6 +16160,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -15967,6 +16220,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -16001,6 +16259,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -16025,6 +16288,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -17156,6 +17424,7 @@ [Out] out ulong contextCount #endregion + } } diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.UWP.Generated.cs b/ClearScript/V8/SplitProxy/V8SplitProxyNative.UWP.Generated.cs index 5be31a3a9..adee0b98a 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.UWP.Generated.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.UWP.Generated.cs @@ -4,6 +4,11 @@ + + + + + // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. @@ -19,35 +24,42 @@ private static IV8SplitProxyNative CreateInstance() var architecture = RuntimeInformation.ProcessArchitecture; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + if (architecture == Architecture.X86) { return new Impl_Windows_X86(); } + if (architecture == Architecture.X64) { return new Impl_Windows_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_Windows_Arm64(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + throw new PlatformNotSupportedException("Unsupported operating system"); } + #region Nested type: Impl_Windows_X86 private sealed class Impl_Windows_X86 : IV8SplitProxyNative @@ -88,6 +100,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -740,6 +757,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -937,6 +959,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -992,6 +1019,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -1026,6 +1058,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -1050,6 +1087,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -2181,6 +2223,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_X64 private sealed class Impl_Windows_X64 : IV8SplitProxyNative @@ -2221,6 +2264,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -2873,6 +2921,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -3070,6 +3123,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -3125,6 +3183,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -3159,6 +3222,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -3183,6 +3251,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -4314,6 +4387,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_Arm64 private sealed class Impl_Windows_Arm64 : IV8SplitProxyNative @@ -4354,6 +4428,11 @@ string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) return Marshal.PtrToStringUni(pValue, length); } + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) { StdString_SetValue(pString, value, value.Length); @@ -5006,6 +5085,11 @@ object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, stri } } + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -5203,6 +5287,11 @@ object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, st } } + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) { using (var nameScope = StdString.CreateScope(name)) @@ -5258,6 +5347,11 @@ object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, } } + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) { using (var valueScope = V8Value.CreateScope(value)) @@ -5292,6 +5386,11 @@ object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConst } } + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) { using (var nameScope = StdString.CreateScope(name)) @@ -5316,6 +5415,11 @@ void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObje } } + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) { V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); @@ -6447,6 +6551,7 @@ [Out] out ulong contextCount #endregion + } } diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.cs b/ClearScript/V8/SplitProxy/V8SplitProxyNative.cs index b1ca55b79..567f29cd7 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.cs @@ -8,13 +8,13 @@ namespace Microsoft.ClearScript.V8.SplitProxy { internal static partial class V8SplitProxyNative { - private static readonly IV8SplitProxyNative instance = CreateInstance(); + internal static readonly IV8SplitProxyNative Instance = CreateInstance(); public static string GetVersion() { try { - return instance.V8SplitProxyNative_GetVersion(); + return Instance.V8SplitProxyNative_GetVersion(); } catch (EntryPointNotFoundException) { @@ -22,70 +22,66 @@ public static string GetVersion() } } - public static void Invoke(Action action) + public static InvokeScope Invoke(out IV8SplitProxyNative instance) { var previousScheduledException = MiscHelpers.Exchange(ref V8SplitProxyManaged.ScheduledException, null); - var previousMethodTable = instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); - try - { - action(instance); - ThrowScheduledException(); - } - finally - { - instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); - V8SplitProxyManaged.ScheduledException = previousScheduledException; - } + var previousMethodTable = Instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); + instance = Instance; + return new InvokeScope(previousScheduledException, previousMethodTable); } - public static T Invoke(Func func) + public static InvokeNoThrowScope InvokeNoThrow(out IV8SplitProxyNative instance) { - var previousScheduledException = MiscHelpers.Exchange(ref V8SplitProxyManaged.ScheduledException, null); - var previousMethodTable = instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); - try - { - var result = func(instance); - ThrowScheduledException(); - return result; - } - finally - { - instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); - V8SplitProxyManaged.ScheduledException = previousScheduledException; - } + var previousMethodTable = Instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); + instance = Instance; + return new InvokeNoThrowScope(previousMethodTable); } - public static void InvokeNoThrow(Action action) + private static void ThrowScheduledException() { - var previousMethodTable = instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); - try - { - action(instance); - } - finally + if (V8SplitProxyManaged.ScheduledException != null) { - instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); + throw V8SplitProxyManaged.ScheduledException; } } - public static T InvokeNoThrow(Func func) + public readonly ref struct InvokeNoThrowScope { - var previousMethodTable = instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); - try + private readonly IntPtr previousMethodTable; + + public InvokeNoThrowScope(IntPtr previousMethodTable) { - return func(instance); + this.previousMethodTable = previousMethodTable; } - finally + + public void Dispose() { - instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); + Instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); } } - private static void ThrowScheduledException() + public readonly ref struct InvokeScope { - if (V8SplitProxyManaged.ScheduledException != null) + private readonly Exception previousScheduledException; + private readonly IntPtr previousMethodTable; + + public InvokeScope(Exception previousScheduledException, IntPtr previousMethodTable) { - throw V8SplitProxyManaged.ScheduledException; + this.previousScheduledException = previousScheduledException; + this.previousMethodTable = previousMethodTable; + } + + public void Dispose() + { + try + { + ThrowScheduledException(); + } + finally + { + Instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); + V8SplitProxyManaged.ScheduledException = previousScheduledException; + } } } } diff --git a/ClearScript/V8/SplitProxy/V8TestProxyImpl.cs b/ClearScript/V8/SplitProxy/V8TestProxyImpl.cs index eebc1f748..13f76e1c5 100644 --- a/ClearScript/V8/SplitProxy/V8TestProxyImpl.cs +++ b/ClearScript/V8/SplitProxy/V8TestProxyImpl.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -9,13 +9,21 @@ internal sealed class V8TestProxyImpl : V8TestProxy { public override UIntPtr GetNativeDigest(string value) { - return V8SplitProxyNative.InvokeNoThrow(instance => instance.V8UnitTestSupport_GetTextDigest(value)); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + return instance.V8UnitTestSupport_GetTextDigest(value); + } } public override Statistics GetStatistics() { var statistics = new Statistics(); - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8UnitTestSupport_GetStatistics(out statistics.IsolateCount, out statistics.ContextCount)); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8UnitTestSupport_GetStatistics(out statistics.IsolateCount, out statistics.ContextCount); + } + return statistics; } diff --git a/ClearScript/V8/V8Proxy.cs b/ClearScript/V8/V8Proxy.cs index a0d4898d7..2d107c713 100644 --- a/ClearScript/V8/V8Proxy.cs +++ b/ClearScript/V8/V8Proxy.cs @@ -169,8 +169,10 @@ private static unsafe void InitializeICU() fixed (byte* pBytes = bytes) { - var pICUData = (IntPtr)pBytes; - V8SplitProxyNative.InvokeNoThrow(instance => instance.V8Environment_InitializeICU(pICUData, Convert.ToUInt32(length))); + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Environment_InitializeICU((IntPtr)pBytes, Convert.ToUInt32(length)); + } } } } diff --git a/ClearScript/V8/V8ProxyHelpers.cs b/ClearScript/V8/V8ProxyHelpers.cs index fccefadce..a683f534e 100644 --- a/ClearScript/V8/V8ProxyHelpers.cs +++ b/ClearScript/V8/V8ProxyHelpers.cs @@ -205,7 +205,9 @@ public static object MarshalExceptionToScript(IntPtr pSource, Exception exceptio public static object MarshalExceptionToScript(object source, Exception exception) { - return ((IScriptMarshalWrapper)source).Engine.MarshalToScript(exception); + return source is IScriptMarshalWrapper scriptMarshalWrapper + ? scriptMarshalWrapper.Engine.MarshalToScript(exception) + : ScriptEngine.Current?.MarshalToScript(exception); } public static Exception MarshalExceptionToHost(object exception) diff --git a/ClearScript/V8/V8ScriptEngine.cs b/ClearScript/V8/V8ScriptEngine.cs index e88d3209d..80850ab21 100644 --- a/ClearScript/V8/V8ScriptEngine.cs +++ b/ClearScript/V8/V8ScriptEngine.cs @@ -1053,6 +1053,8 @@ public void WriteRuntimeHeapSnapshot(Stream stream) #region internal members + internal V8ContextProxy ContextProxy => proxy; + internal V8Runtime.Statistics GetRuntimeStatistics() { VerifyNotDisposed(); @@ -1480,10 +1482,21 @@ internal override void AddHostItem(string itemName, HostItemFlags flags, object ScriptInvoke(() => { - var marshaledItem = MarshalToScript(item, flags); - if (!(marshaledItem is HostItem)) + object marshaledItem; + +#if NETCOREAPP || NETSTANDARD + if (item is SplitProxy.IV8HostObject || item is SplitProxy.InvokeHostObject) { - throw new InvalidOperationException("Invalid host item"); + marshaledItem = item; + } + else +#endif + { + marshaledItem = MarshalToScript(item, flags); + if (!(marshaledItem is HostItem)) + { + throw new InvalidOperationException("Invalid host item"); + } } proxy.AddGlobalItem(itemName, marshaledItem, globalMembers); diff --git a/ClearScriptTest/JScriptCoreEngineTest.cs b/ClearScriptTest/JScriptCoreEngineTest.cs index 0ee8248b9..e73b369ab 100644 --- a/ClearScriptTest/JScriptCoreEngineTest.cs +++ b/ClearScriptTest/JScriptCoreEngineTest.cs @@ -453,7 +453,7 @@ public void JScriptCoreEngine_AccessContext_Private() engine.Execute("test.PrivateMethod()"); } - [TestMethod, TestCategory("JScriptCoreEngine")] + [TestMethod, TestCategory("JScriptCoreEngine"), Timeout(1000)] public void JScriptCoreEngine_ContinuationCallback() { engine.ContinuationCallback = () => false; diff --git a/ClearScriptTest/JScriptEngineTest.cs b/ClearScriptTest/JScriptEngineTest.cs index 5039f45a3..b19bdf1ae 100644 --- a/ClearScriptTest/JScriptEngineTest.cs +++ b/ClearScriptTest/JScriptEngineTest.cs @@ -452,7 +452,7 @@ public void JScriptEngine_AccessContext_Private() engine.Execute("test.PrivateMethod()"); } - [TestMethod, TestCategory("JScriptEngine")] + [TestMethod, TestCategory("JScriptEngine"), Timeout(1000)] public void JScriptEngine_ContinuationCallback() { engine.ContinuationCallback = () => false; diff --git a/ClearScriptV8/V8Platform.h b/ClearScriptV8/V8Platform.h index ed6367254..dd079dd6e 100644 --- a/ClearScriptV8/V8Platform.h +++ b/ClearScriptV8/V8Platform.h @@ -26,7 +26,11 @@ #endif // INTPTR_MAX == INT64_MAX #endif // CLEARSCRIPT_V8_POINTER_COMPRESSION_ENABLED +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-mismatch" #include "v8.h" +#pragma clang diagnostic pop + #include "v8-platform.h" #include "v8-inspector.h" #include "v8-profiler.h" diff --git a/NetCore/ClearScript.Core/ClearScript.Core.csproj b/NetCore/ClearScript.Core/ClearScript.Core.csproj index 03600f153..aef8b9586 100644 --- a/NetCore/ClearScript.Core/ClearScript.Core.csproj +++ b/NetCore/ClearScript.Core/ClearScript.Core.csproj @@ -121,6 +121,7 @@ + diff --git a/NetCore/ClearScript.V8/ClearScript.V8.csproj b/NetCore/ClearScript.V8/ClearScript.V8.csproj index 43cd71406..4d73d0a60 100644 --- a/NetCore/ClearScript.V8/ClearScript.V8.csproj +++ b/NetCore/ClearScript.V8/ClearScript.V8.csproj @@ -39,8 +39,10 @@ + + diff --git a/NetFramework/ClearScript.Core/ClearScript.Core.csproj b/NetFramework/ClearScript.Core/ClearScript.Core.csproj index f5ffe3805..d1900c8e9 100644 --- a/NetFramework/ClearScript.Core/ClearScript.Core.csproj +++ b/NetFramework/ClearScript.Core/ClearScript.Core.csproj @@ -124,6 +124,7 @@ + diff --git a/NetFramework/ClearScript.V8/ClearScript.V8.csproj b/NetFramework/ClearScript.V8/ClearScript.V8.csproj index ea73290b4..31d6e2541 100644 --- a/NetFramework/ClearScript.V8/ClearScript.V8.csproj +++ b/NetFramework/ClearScript.V8/ClearScript.V8.csproj @@ -4,6 +4,7 @@ net45;net471 Microsoft.ClearScript.V8 false + 8.0 @@ -44,6 +45,7 @@ + @@ -101,12 +103,12 @@ TextTemplatingFileGenerator V8ScriptEngine.InitScript.cs - + TextTemplatingFileGenerator V8SplitProxyNative.Generated.cs - + diff --git a/NetStandard/ClearScript.Core/ClearScript.Core.csproj b/NetStandard/ClearScript.Core/ClearScript.Core.csproj index b75f631cc..9bf702389 100644 --- a/NetStandard/ClearScript.Core/ClearScript.Core.csproj +++ b/NetStandard/ClearScript.Core/ClearScript.Core.csproj @@ -4,6 +4,7 @@ netstandard2.1 Microsoft.ClearScript false + 10 @@ -120,6 +121,7 @@ + diff --git a/NetStandard/ClearScript.V8/ClearScript.V8.csproj b/NetStandard/ClearScript.V8/ClearScript.V8.csproj index 11e14a783..08859dfc2 100644 --- a/NetStandard/ClearScript.V8/ClearScript.V8.csproj +++ b/NetStandard/ClearScript.V8/ClearScript.V8.csproj @@ -38,8 +38,10 @@ + + diff --git a/UWP/ClearScript.Core/ClearScript.Core.csproj b/UWP/ClearScript.Core/ClearScript.Core.csproj index 35400652e..9553c898b 100644 --- a/UWP/ClearScript.Core/ClearScript.Core.csproj +++ b/UWP/ClearScript.Core/ClearScript.Core.csproj @@ -1,221 +1,222 @@ - - - - - - - Debug - AnyCPU - {D3391831-65CE-4C1E-A21B-01A283F3E193} - Library - Properties - Microsoft.ClearScript - ClearScript.Core - en-US - UAP - 10.0.20348.0 - 10.0.17763.0 - 14 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - AnyCPU - true - portable - false - ..\..\bin\Debug\uap10.0\ - TRACE;DEBUG;UWP - prompt - 4 - true - true - CS0618 - - - ..\..\bin\Debug\uap10.0\ClearScript.Core.xml - - - AnyCPU - portable - true - ..\..\bin\Release\uap10.0\ - TRACE;UWP - prompt - 4 - true - true - CS0618 - - - ..\..\bin\Release\uap10.0\ClearScript.Core.xml - true - - - true - $(SolutionDir)ClearScript.snk - - - true - $(SolutionDir)ClearScript.DelaySign.snk - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PackageReference - - - - - - - 6.2.14 - - - - 14.0 - - - + + + + + + + Debug + AnyCPU + {D3391831-65CE-4C1E-A21B-01A283F3E193} + Library + Properties + Microsoft.ClearScript + ClearScript.Core + en-US + UAP + 10.0.20348.0 + 10.0.17763.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + AnyCPU + true + portable + false + ..\..\bin\Debug\uap10.0\ + TRACE;DEBUG;UWP + prompt + 4 + true + true + CS0618 + + + ..\..\bin\Debug\uap10.0\ClearScript.Core.xml + + + AnyCPU + portable + true + ..\..\bin\Release\uap10.0\ + TRACE;UWP + prompt + 4 + true + true + CS0618 + + + ..\..\bin\Release\uap10.0\ClearScript.Core.xml + true + + + true + $(SolutionDir)ClearScript.snk + + + true + $(SolutionDir)ClearScript.DelaySign.snk + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PackageReference + + + + + + + 6.2.14 + + + + 14.0 + + + \ No newline at end of file diff --git a/UWP/ClearScript.V8/ClearScript.V8.csproj b/UWP/ClearScript.V8/ClearScript.V8.csproj index 9a7cbd97b..7f8de5db0 100644 --- a/UWP/ClearScript.V8/ClearScript.V8.csproj +++ b/UWP/ClearScript.V8/ClearScript.V8.csproj @@ -1,149 +1,151 @@ - - - - - - - Debug - AnyCPU - {CF1FD52F-A933-48D9-92A4-A39565896A42} - Library - Properties - Microsoft.ClearScript.V8 - ClearScript.V8 - en-US - UAP - - 10.0.20348.0 - 10.0.17763.0 - 14 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - AnyCPU - true - portable - false - ..\..\bin\Debug\uap10.0\ - TRACE;DEBUG;UWP - prompt - 4 - ..\..\bin\Debug\uap10.0\ClearScript.V8.xml - true - - - AnyCPU - portable - true - ..\..\bin\Release\uap10.0\ - TRACE;UWP - prompt - 4 - ..\..\bin\Release\uap10.0\ClearScript.V8.xml - true - true - - - true - $(SolutionDir)ClearScript.snk - - - true - $(SolutionDir)ClearScript.DelaySign.snk - true - - - - - - - - - - - - - - - - - - V8\SplitProxy\V8SplitProxyNative.UWP.Generated.cs - True - True - V8SplitProxyNative.UWP.tt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PackageReference - - - - - - - 6.2.14 - - - 13.0.2 - - - - - {47fc5cb5-a6f2-4fee-99f8-a758d3a7373c} - ClearScript.V8.ICUData - - - {d3391831-65ce-4c1e-a21b-01a283f3e193} - ClearScript.Core - - - - - - - - V8\SplitProxy\V8SplitProxyNative.UWP.tt - TextTemplatingFileGenerator - V8SplitProxyNative.UWP.Generated.cs - - - V8\SplitProxy\V8SplitProxyNative.Common.tt - - - - - 14.0 - - - - + + + + + + + Debug + AnyCPU + {CF1FD52F-A933-48D9-92A4-A39565896A42} + Library + Properties + Microsoft.ClearScript.V8 + ClearScript.V8 + en-US + UAP + + 10.0.20348.0 + 10.0.17763.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 8.0 + + + AnyCPU + true + portable + false + ..\..\bin\Debug\uap10.0\ + TRACE;DEBUG;UWP + prompt + 4 + ..\..\bin\Debug\uap10.0\ClearScript.V8.xml + true + + + AnyCPU + portable + true + ..\..\bin\Release\uap10.0\ + TRACE;UWP + prompt + 4 + ..\..\bin\Release\uap10.0\ClearScript.V8.xml + true + true + + + true + $(SolutionDir)ClearScript.snk + + + true + $(SolutionDir)ClearScript.DelaySign.snk + true + + + + + + + + + + + + + + + + + + + V8\SplitProxy\V8SplitProxyNative.UWP.Generated.cs + True + True + V8SplitProxyNative.UWP.tt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PackageReference + + + + + + + 6.2.14 + + + 13.0.2 + + + + + {47fc5cb5-a6f2-4fee-99f8-a758d3a7373c} + ClearScript.V8.ICUData + + + {d3391831-65ce-4c1e-a21b-01a283f3e193} + ClearScript.Core + + + + + + + + V8\SplitProxy\V8SplitProxyNative.UWP.tt + TextTemplatingFileGenerator + V8SplitProxyNative.UWP.Generated.cs + + + V8\SplitProxy\V8SplitProxyNative.Common.tt + + + + + 14.0 + + + + \ No newline at end of file diff --git a/Unity/Package/.editorconfig b/Unity/Package/.editorconfig new file mode 100644 index 000000000..677e36e29 --- /dev/null +++ b/Unity/Package/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/Unity/Package/Plugins.meta b/Unity/Package/Plugins.meta new file mode 100644 index 000000000..822837c73 --- /dev/null +++ b/Unity/Package/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93a4305e85e252e41b0737db330f3250 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScript.V8.ICUData.dll b/Unity/Package/Plugins/ClearScript.V8.ICUData.dll new file mode 100644 index 000000000..af2ca87b2 Binary files /dev/null and b/Unity/Package/Plugins/ClearScript.V8.ICUData.dll differ diff --git a/Unity/Package/Plugins/ClearScript.V8.ICUData.dll.meta b/Unity/Package/Plugins/ClearScript.V8.ICUData.dll.meta new file mode 100644 index 000000000..23307e239 --- /dev/null +++ b/Unity/Package/Plugins/ClearScript.V8.ICUData.dll.meta @@ -0,0 +1,69 @@ +fileFormatVersion: 2 +guid: 7fdd7a24aa2be624c8a0429eab8b7665 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScriptV8.linux-x64.so b/Unity/Package/Plugins/ClearScriptV8.linux-x64.so new file mode 100644 index 000000000..49d41155f Binary files /dev/null and b/Unity/Package/Plugins/ClearScriptV8.linux-x64.so differ diff --git a/Unity/Package/Plugins/ClearScriptV8.linux-x64.so.meta b/Unity/Package/Plugins/ClearScriptV8.linux-x64.so.meta new file mode 100644 index 000000000..c6af637b0 --- /dev/null +++ b/Unity/Package/Plugins/ClearScriptV8.linux-x64.so.meta @@ -0,0 +1,46 @@ +fileFormatVersion: 2 +guid: 464546895c69cdf4dbdebcd149ec6824 +PluginImporter: + externalObjects: {} + serializedVersion: 3 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + Any: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 1 + Exclude Win: 0 + Exclude Win64: 0 + Editor: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Linux + Linux64: + enabled: 1 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 0 + settings: + CPU: None + Win: + enabled: 1 + settings: + CPU: None + Win64: + enabled: 1 + settings: + CPU: None + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib b/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib new file mode 100755 index 000000000..c4d488541 Binary files /dev/null and b/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib differ diff --git a/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib.meta b/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib.meta new file mode 100644 index 000000000..2bc383117 --- /dev/null +++ b/Unity/Package/Plugins/ClearScriptV8.osx-arm64.dylib.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: d665fb43a76704f2a9a646ec87f292b8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: ARM64 + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib b/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib new file mode 100755 index 000000000..4dfcbe596 Binary files /dev/null and b/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib differ diff --git a/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib.meta b/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib.meta new file mode 100644 index 000000000..616ca7ebb --- /dev/null +++ b/Unity/Package/Plugins/ClearScriptV8.osx-x64.dylib.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 7a0c07fc218864423ae2fb2330cfa54a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll b/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll new file mode 100644 index 000000000..4933a7a96 Binary files /dev/null and b/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll differ diff --git a/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll.meta b/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll.meta new file mode 100644 index 000000000..e4eae683c --- /dev/null +++ b/Unity/Package/Plugins/ClearScriptV8.win-arm64.dll.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 26d7de65dffcc434fa10c11d1363c98c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/ClearScriptV8.win-x64.dll b/Unity/Package/Plugins/ClearScriptV8.win-x64.dll new file mode 100644 index 000000000..a8e2e4ccb Binary files /dev/null and b/Unity/Package/Plugins/ClearScriptV8.win-x64.dll differ diff --git a/Unity/Package/Plugins/ClearScriptV8.win-x64.dll.meta b/Unity/Package/Plugins/ClearScriptV8.win-x64.dll.meta new file mode 100644 index 000000000..32ab0691f --- /dev/null +++ b/Unity/Package/Plugins/ClearScriptV8.win-x64.dll.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 6b8bcd0b8b50c5941bace05e1ed0cceb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Plugins/Microsoft.CSharp.dll b/Unity/Package/Plugins/Microsoft.CSharp.dll new file mode 100644 index 000000000..3f093f5d4 Binary files /dev/null and b/Unity/Package/Plugins/Microsoft.CSharp.dll differ diff --git a/Unity/Package/Plugins/Microsoft.CSharp.dll.meta b/Unity/Package/Plugins/Microsoft.CSharp.dll.meta new file mode 100644 index 000000000..cb62ee997 --- /dev/null +++ b/Unity/Package/Plugins/Microsoft.CSharp.dll.meta @@ -0,0 +1,70 @@ +fileFormatVersion: 2 +guid: 2cfdf060373f811449bc47d79ccbc941 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: + - '!NET_4_6' + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime.meta b/Unity/Package/Runtime.meta new file mode 100644 index 000000000..fe970100c --- /dev/null +++ b/Unity/Package/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3c00602ec9ffa5246a8fb1cad922c5d2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs b/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs new file mode 100644 index 000000000..1e7ba867a --- /dev/null +++ b/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a method to be called asynchronously when a document is loaded. + /// + /// A structure containing meta-information for the document. + /// A stream that provides read access to the document. + /// A task that represents the method's asynchronous operation. + /// + /// The callback can modify the document meta-information by specifying or overriding any of + /// its mutable properties. + /// + public delegate Task AsyncDocumentLoadCallback(ValueRef info, Stream contents); +} diff --git a/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs.meta b/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs.meta new file mode 100644 index 000000000..7009159ed --- /dev/null +++ b/Unity/Package/Runtime/AsyncDocumentLoadCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fac67b500d3964648b9bfda4cd8fea86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/BindSignature.cs b/Unity/Package/Runtime/BindSignature.cs new file mode 100644 index 000000000..c1ebe9de2 --- /dev/null +++ b/Unity/Package/Runtime/BindSignature.cs @@ -0,0 +1,347 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class BindSignature : IEquatable + { + private readonly Type context; + private readonly BindingFlags flags; + private readonly TargetInfo targetInfo; + private readonly string name; + private readonly Type[] typeArgs; + private readonly ArgInfo[] argData; + + public BindSignature(Type context, BindingFlags flags, HostTarget target, string name, Type[] typeArgs, object[] args) + { + this.context = context; + this.flags = flags; + targetInfo = new TargetInfo(target); + this.name = name; + this.typeArgs = typeArgs; + + argData = new ArgInfo[args.Length]; + for (var index = 0; index < args.Length; index++) + { + argData[index] = new ArgInfo(args[index]); + } + } + + #region Object overrides + + public override bool Equals(object obj) + { + return Equals(obj as BindSignature); + } + + public override int GetHashCode() + { + var accumulator = new HashAccumulator(); + + accumulator.Update(context); + accumulator.Update((int)flags); + targetInfo.UpdateHash(ref accumulator); + accumulator.Update(name); + + foreach (var type in typeArgs) + { + accumulator.Update(type); + } + + foreach (var argInfo in argData) + { + argInfo.UpdateHash(ref accumulator); + } + + return accumulator.HashCode; + } + + #endregion + + #region IEquatable implementation + + public bool Equals(BindSignature that) + { + if (that == null) + { + return false; + } + + if (context != that.context) + { + return false; + } + + if (flags != that.flags) + { + return false; + } + + if (!targetInfo.Equals(that.targetInfo)) + { + return false; + } + + if (name != that.name) + { + return false; + } + + if (typeArgs.Length != that.typeArgs.Length) + { + return false; + } + + for (var index = 0; index < typeArgs.Length; index++) + { + if (typeArgs[index] != that.typeArgs[index]) + { + return false; + } + } + + if (argData.Length != that.argData.Length) + { + return false; + } + + for (var index = 0; index < argData.Length; index++) + { + if (!argData[index].Equals(that.argData[index])) + { + return false; + } + } + + return true; + } + + #endregion + + #region Nested type: TargetKind + + private enum TargetKind + { + Static, + Null, + Instance + } + + #endregion + + #region Nested type: TargetInfo + + private sealed class TargetInfo : IEquatable + { + private readonly TargetKind kind; + private readonly Type targetType; + private readonly Type instanceType; + + public TargetInfo(HostTarget target) + { + if (target is HostType) + { + kind = TargetKind.Static; + targetType = target.Type; + } + else if (target.InvokeTarget == null) + { + kind = TargetKind.Null; + targetType = target.Type; + } + else + { + kind = TargetKind.Instance; + targetType = target.Type; + + var tempType = target.InvokeTarget.GetType(); + if (tempType != targetType) + { + instanceType = tempType; + } + } + } + + public void UpdateHash(ref HashAccumulator accumulator) + { + accumulator.Update((int)kind); + accumulator.Update(targetType); + accumulator.Update(instanceType); + } + + #region Object overrides + + public override bool Equals(object obj) + { + return Equals(obj as TargetInfo); + } + + public override int GetHashCode() + { + var accumulator = new HashAccumulator(); + UpdateHash(ref accumulator); + return accumulator.HashCode; + } + + #endregion + + #region IEquatable implementation + + public bool Equals(TargetInfo that) + { + return (that != null) && (kind == that.kind) && (targetType == that.targetType) && (instanceType == that.instanceType); + } + + #endregion + } + + #endregion + + #region Nested type: ArgKind + + private enum ArgKind + { + Null, + Zero, + ByValue, + Out, + Ref + } + + #endregion + + #region Nested type: ArgInfo + + private sealed class ArgInfo : IEquatable + { + private readonly ArgKind kind; + private readonly Type type; + + public ArgInfo(object arg) + { + if (arg == null) + { + kind = ArgKind.Null; + return; + } + + if (arg is IOutArg outArg) + { + kind = ArgKind.Out; + type = outArg.Type; + return; + } + + if (arg is IRefArg refArg) + { + kind = ArgKind.Ref; + type = refArg.Type; + return; + } + + if (arg is HostType) + { + kind = ArgKind.ByValue; + type = typeof(HostType); + return; + } + + if (arg is HostMethod) + { + kind = ArgKind.ByValue; + type = typeof(HostMethod); + return; + } + + if (arg is HostIndexedProperty) + { + kind = ArgKind.ByValue; + type = typeof(HostIndexedProperty); + return; + } + + if (arg is ScriptMethod) + { + kind = ArgKind.ByValue; + type = typeof(ScriptMethod); + return; + } + + if (arg is HostObject hostObject) + { + kind = hostObject.Target.IsZero() ? ArgKind.Zero : ArgKind.ByValue; + type = hostObject.Type; + return; + } + + if (arg is HostVariable hostVariable) + { + kind = hostVariable.Target.IsZero() ? ArgKind.Zero : ArgKind.ByValue; + type = hostVariable.Type; + return; + } + + Debug.Assert(!(arg is HostTarget)); + kind = arg.IsZero() ? ArgKind.Zero : ArgKind.ByValue; + type = arg.GetType(); + } + + public void UpdateHash(ref HashAccumulator accumulator) + { + accumulator.Update((int)kind); + accumulator.Update(type); + } + + #region Object overrides + + public override bool Equals(object obj) + { + return Equals(obj as ArgInfo); + } + + public override int GetHashCode() + { + var accumulator = new HashAccumulator(); + UpdateHash(ref accumulator); + return accumulator.HashCode; + } + + #endregion + + #region IEquatable implementation + + public bool Equals(ArgInfo that) + { + return (that != null) && (kind == that.kind) && (type == that.type); + } + + #endregion + } + + #endregion + + #region Nested type: HashAccumulator + + private struct HashAccumulator + { + public int HashCode { get; private set; } + + public void Update(int value) + { + HashCode = unchecked((HashCode * 31) + value); + } + + public void Update(object obj) + { + HashCode = unchecked((HashCode * 31) + (obj?.GetHashCode() ?? 0)); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/BindSignature.cs.meta b/Unity/Package/Runtime/BindSignature.cs.meta new file mode 100644 index 000000000..859952639 --- /dev/null +++ b/Unity/Package/Runtime/BindSignature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 503ff481c05c87746b1937f0f796dab4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ByRefArg.cs b/Unity/Package/Runtime/ByRefArg.cs new file mode 100644 index 000000000..28428fd1a --- /dev/null +++ b/Unity/Package/Runtime/ByRefArg.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal interface IByRefArg + { + Type Type { get; } + object Value { get; set; } + } + + internal interface IOutArg : IByRefArg + { + } + + internal interface IRefArg : IByRefArg + { + } + + internal abstract class ByRefArg : HostTarget, IByRefArg + { + private readonly HostVariable target; + + protected ByRefArg(HostVariable target) + { + this.target = target; + } + + public T Value + { + get => target.Value; + set => target.Value = value; + } + + #region HostTarget overrides + + public override Type Type => target.Type; + + public override object Target => this; + + public override object InvokeTarget => target.InvokeTarget; + + public override object DynamicInvokeTarget => target.DynamicInvokeTarget; + + public override HostTargetFlags GetFlags(IHostContext context) + { + return target.GetFlags(context); + } + + public override string[] GetAuxMethodNames(IHostContext context, BindingFlags bindFlags) + { + return target.GetAuxMethodNames(context, bindFlags); + } + + public override string[] GetAuxPropertyNames(IHostContext context, BindingFlags bindFlags) + { + return target.GetAuxPropertyNames(context, bindFlags); + } + + public override bool TryInvokeAuxMember(IHostContext context, string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + return target.TryInvokeAuxMember(context, name, invokeFlags, args, bindArgs, out result); + } + + public override bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + return target.TryInvoke(context, invokeFlags, args, bindArgs, out result); + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return target.GetInvocability(context, bindFlags, ignoreDynamic); + } + + #endregion + + #region IByRefArg implementation + + object IByRefArg.Value + { + get => target.Value; + set => ((IHostVariable)target).Value = value; + } + + #endregion + } + + internal sealed class OutArg : ByRefArg, IOutArg + { + public OutArg(HostVariable target) + : base(target) + { + } + + public OutArg(T initValue) + : this(new HostVariable(initValue)) + { + } + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("out {0}", Type.GetFriendlyName()); + } + + #endregion + } + + internal sealed class RefArg : ByRefArg, IRefArg + { + public RefArg(HostVariable target) + : base(target) + { + } + + public RefArg(T initValue) + : this(new HostVariable(initValue)) + { + } + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("ref {0}", Type.GetFriendlyName()); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/ByRefArg.cs.meta b/Unity/Package/Runtime/ByRefArg.cs.meta new file mode 100644 index 000000000..3001f9cbb --- /dev/null +++ b/Unity/Package/Runtime/ByRefArg.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6282d4967ee9f944970970fc6aa4832 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/CanonicalRefTable.cs b/Unity/Package/Runtime/CanonicalRefTable.cs new file mode 100644 index 000000000..287763919 --- /dev/null +++ b/Unity/Package/Runtime/CanonicalRefTable.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal static class CanonicalRefTable + { + private static readonly Dictionary table = new Dictionary(); + + public static object GetCanonicalRef(object obj) + { + if (obj is ValueType) + { + var map = GetMap(obj); + if (map != null) + { + obj = map.GetRef(obj); + } + } + + return obj; + } + + private static ICanonicalRefMap GetMap(object obj) + { + var type = obj.GetType(); + lock (table) + { + if (!table.TryGetValue(type, out var map)) + { + if (type.IsEnum || + type.IsNumeric() || + type == typeof(DateTime) || + type == typeof(DateTimeOffset) || + type == typeof(TimeSpan) || + type == typeof(Guid) || + #if NET471_OR_GREATER || NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + type.GetOrLoadCustomAttributes(null, false).Any() || + #endif + type.GetOrLoadCustomAttributes(null, false).Any()) + { + map = (ICanonicalRefMap)typeof(CanonicalRefMap<>).MakeGenericType(type).CreateInstance(); + } + + table.Add(type, map); + } + + return map; + } + } + + #region Nested type: ICanonicalRefMap + + private interface ICanonicalRefMap + { + object GetRef(object obj); + } + + #endregion + + #region Nested type: CanonicalRefMapBase + + private abstract class CanonicalRefMapBase : ICanonicalRefMap + { + protected const int CompactionThreshold = 256 * 1024; + protected static readonly TimeSpan CompactionInterval = TimeSpan.FromMinutes(2); + + #region ICanonicalRefMap implementation + + public abstract object GetRef(object obj); + + #endregion + } + + #endregion + + #region Nested type: CanonicalRefMap + + private sealed class CanonicalRefMap : CanonicalRefMapBase + { + private readonly Dictionary map = new Dictionary(); + private DateTime lastCompactionTime = DateTime.MinValue; + + private object GetRefInternal(object obj) + { + var value = (T)obj; + object result; + + if (map.TryGetValue(value, out var weakRef)) + { + result = weakRef.Target; + if (result == null) + { + result = obj; + weakRef.Target = result; + } + } + else + { + result = obj; + map.Add(value, new WeakReference(result)); + } + + return result; + } + + private void CompactIfNecessary() + { + if (map.Count >= CompactionThreshold) + { + var now = DateTime.UtcNow; + if ((lastCompactionTime + CompactionInterval) <= now) + { + map.Where(pair => !pair.Value.IsAlive).ToList().ForEach(pair => map.Remove(pair.Key)); + lastCompactionTime = now; + } + } + } + + #region CanonicalRefMapBase overrides + + public override object GetRef(object obj) + { + lock (map) + { + var result = GetRefInternal(obj); + CompactIfNecessary(); + return result; + } + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/Unity/Package/Runtime/CanonicalRefTable.cs.meta b/Unity/Package/Runtime/CanonicalRefTable.cs.meta new file mode 100644 index 000000000..4e1ec132b --- /dev/null +++ b/Unity/Package/Runtime/CanonicalRefTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4bd6cfd1188aa0947b796dabb92bdd4c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ContinuationCallback.cs b/Unity/Package/Runtime/ContinuationCallback.cs new file mode 100644 index 000000000..b95956fbe --- /dev/null +++ b/Unity/Package/Runtime/ContinuationCallback.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Represents a method that specifies to a script engine whether script execution should continue. + /// + /// True to continue script execution, false to interrupt it. + /// + public delegate bool ContinuationCallback(); +} diff --git a/Unity/Package/Runtime/ContinuationCallback.cs.meta b/Unity/Package/Runtime/ContinuationCallback.cs.meta new file mode 100644 index 000000000..1120316ff --- /dev/null +++ b/Unity/Package/Runtime/ContinuationCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 831e9affd2877424ead9851e3cf1bb41 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/CustomAttributeCache.cs b/Unity/Package/Runtime/CustomAttributeCache.cs new file mode 100644 index 000000000..22d6eacbe --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributeCache.cs @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class CustomAttributeCache + { + private readonly ConditionalWeakTable table = new ConditionalWeakTable(); + + public T[] GetOrLoad(CustomAttributeLoader loader, ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + lock (table) + { + return GetOrLoad(loader, table.GetOrCreateValue(resource), resource, inherit); + } + } + + private T[] GetOrLoad(CustomAttributeLoader loader, Entry entry, ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + if (entry.TryGet(out var attrs)) + { + return attrs; + } + + attrs = Load(GetIsBypass(entry, resource) ? CustomAttributeLoader.Default : loader, resource, inherit); + entry.Add(attrs); + + return attrs; + } + + private static T[] Load(CustomAttributeLoader loader, ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + return loader.LoadCustomAttributes(resource, inherit) ?? ArrayHelpers.GetEmptyArray(); + } + + private bool GetIsBypass(ICustomAttributeProvider resource) + { + // ReSharper disable once InconsistentlySynchronizedField + return GetIsBypass(table.GetOrCreateValue(resource), resource); + } + + private bool GetIsBypass(Entry entry, ICustomAttributeProvider resource) + { + if (!entry.IsBypass.HasValue) + { + entry.IsBypass = GetIsBypassInternal(resource); + } + + return entry.IsBypass.Value; + } + + private bool GetIsBypassInternal(ICustomAttributeProvider resource) + { + if (Load(CustomAttributeLoader.Default, resource, false).Length > 0) + { + return true; + } + + var parent = GetParent(resource); + if (parent != null) + { + return GetIsBypass(parent); + } + + return false; + } + + private static ICustomAttributeProvider GetParent(ICustomAttributeProvider resource) + { + if (resource is ParameterInfo parameter) + { + return parameter.Member; + } + + if (resource is Type type) + { + return (type.DeclaringType as ICustomAttributeProvider) ?? type.Module; + } + + if (resource is MemberInfo member) + { + return member.DeclaringType; + } + + if (resource is Module module) + { + return module.Assembly; + } + + return null; + } + + #region Nested type: Entry + + // ReSharper disable ClassNeverInstantiated.Local + + private sealed class Entry + { + private readonly Dictionary map = new Dictionary(); + + public bool? IsBypass { get; set; } + + public void Add(T[] attrs) + { + map.Add(typeof(T), attrs); + } + + public bool TryGet(out T[] attrs) + { + if (map.TryGetValue(typeof(T), out var attrsObject)) + { + attrs = attrsObject as T[]; + return true; + } + + attrs = null; + return false; + } + } + + // ReSharper restore ClassNeverInstantiated.Local + + #endregion + } + + [AttributeUsage(AttributeTargets.All, Inherited = false)] + internal sealed class BypassCustomAttributeLoaderAttribute : Attribute + { + } +} diff --git a/Unity/Package/Runtime/CustomAttributeCache.cs.meta b/Unity/Package/Runtime/CustomAttributeCache.cs.meta new file mode 100644 index 000000000..31999b868 --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributeCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3e2deed2c1488245b6174838329f43a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/CustomAttributeLoader.cs b/Unity/Package/Runtime/CustomAttributeLoader.cs new file mode 100644 index 000000000..0b2330220 --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributeLoader.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Linq; +using System.Reflection; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a custom attribute loader. + /// + public class CustomAttributeLoader + { + private readonly CustomAttributeCache cache = new CustomAttributeCache(); + + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public CustomAttributeLoader() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + /// + /// Gets the default custom attribute loader. + /// + public static CustomAttributeLoader Default { get; } = new CustomAttributeLoader(); + + // ReSharper restore EmptyConstructor + + /// + /// Loads custom attributes of the specified type for the given resource. + /// + /// The type, or a base type, of the custom attributes to load. + /// The resource for which to load custom attributes of type . + /// True to include custom attributes of type defined for ancestors of , false otherwise. + /// An array of custom attributes of type .. + /// + /// This method is performance-critical. Overrides must not invoke script engine methods or + /// other ClearScript functionality. The base implementation loads custom attributes via + /// reflection. + /// + public virtual T[] LoadCustomAttributes(ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + if (resource is MemberInfo member) + { + return Attribute.GetCustomAttributes(member, typeof(T), inherit).OfType().ToArray(); + } + + if (resource is ParameterInfo parameter) + { + return Attribute.GetCustomAttributes(parameter, typeof(T), inherit).OfType().ToArray(); + } + + if (resource is Assembly assembly) + { + return Attribute.GetCustomAttributes(assembly, typeof(T), inherit).OfType().ToArray(); + } + + if (resource is Module module) + { + return Attribute.GetCustomAttributes(module, typeof(T), inherit).OfType().ToArray(); + } + + return resource.GetCustomAttributes(typeof(T), inherit).OfType().ToArray(); + } + + internal T[] GetOrLoad(ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + return cache.GetOrLoad(this, resource, inherit); + } + } +} diff --git a/Unity/Package/Runtime/CustomAttributeLoader.cs.meta b/Unity/Package/Runtime/CustomAttributeLoader.cs.meta new file mode 100644 index 000000000..902a7f81c --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributeLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93f006514ecbf554b864bb1880a99115 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/CustomAttributes.cs b/Unity/Package/Runtime/CustomAttributes.cs new file mode 100644 index 000000000..aaaec6d0d --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributes.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal static class CustomAttributes + { + public static T[] GetOrLoad(IHostContext context, ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + var loader = context?.CustomAttributeLoader ?? HostSettings.CustomAttributeLoader; + return loader.GetOrLoad(resource, inherit); + } + + public static bool Has(IHostContext context, ICustomAttributeProvider resource, bool inherit) where T : Attribute + { + return GetOrLoad(context, resource, inherit).Length > 0; + } + } +} diff --git a/Unity/Package/Runtime/CustomAttributes.cs.meta b/Unity/Package/Runtime/CustomAttributes.cs.meta new file mode 100644 index 000000000..c9e5a8242 --- /dev/null +++ b/Unity/Package/Runtime/CustomAttributes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 668952dbc517a074b99bce962f26e55d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Decentraland.ClearScript.asmdef b/Unity/Package/Runtime/Decentraland.ClearScript.asmdef new file mode 100644 index 000000000..c8df379d3 --- /dev/null +++ b/Unity/Package/Runtime/Decentraland.ClearScript.asmdef @@ -0,0 +1,24 @@ +{ + "name": "Decentraland.ClearScript", + "rootNamespace": "Microsoft.ClearScript", + "references": [], + "includePlatforms": [ + "Editor", + "LinuxStandalone64", + "macOSStandalone", + "WSA", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": true, + "precompiledReferences": [ + "ClearScript.V8.ICUData.dll", + "Microsoft.CSharp.dll", + "Newtonsoft.Json.dll" + ], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Unity/Package/Runtime/Decentraland.ClearScript.asmdef.meta b/Unity/Package/Runtime/Decentraland.ClearScript.asmdef.meta new file mode 100644 index 000000000..960fd186c --- /dev/null +++ b/Unity/Package/Runtime/Decentraland.ClearScript.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9659fcb6593e30b46909c1245ed056df +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DefaultDocumentLoader.cs b/Unity/Package/Runtime/DefaultDocumentLoader.cs new file mode 100644 index 000000000..fbedfab48 --- /dev/null +++ b/Unity/Package/Runtime/DefaultDocumentLoader.cs @@ -0,0 +1,491 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.ClearScript.Util; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript +{ + /// + /// Provides a default implementation. + /// + public class DefaultDocumentLoader : DocumentLoader, DocumentLoader.IStatistics + { + private static readonly IReadOnlyCollection relativePrefixes = new List + { + "." + Path.DirectorySeparatorChar, + "." + Path.AltDirectorySeparatorChar, + ".." + Path.DirectorySeparatorChar, + ".." + Path.AltDirectorySeparatorChar, + }; + + private readonly List cache = new List(); + private long fileCheckCount; + private long webCheckCount; + + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public DefaultDocumentLoader() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + private Task<(Document, List)> GetCachedDocumentOrCandidateUrisAsync(DocumentSettings settings, DocumentInfo? sourceInfo, Uri uri) + { + return GetCachedDocumentOrCandidateUrisWorkerAsync(settings, sourceInfo, uri.ToEnumerable()); + } + + private Task<(Document, List)> GetCachedDocumentOrCandidateUrisAsync(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier) + { + return GetCachedDocumentOrCandidateUrisWorkerAsync(settings, sourceInfo, GetRawUris(settings, sourceInfo, specifier).Distinct()); + } + + private async Task<(Document, List)> GetCachedDocumentOrCandidateUrisWorkerAsync(DocumentSettings settings, DocumentInfo? sourceInfo, IEnumerable rawUris) + { + if (!string.IsNullOrWhiteSpace(settings.FileNameExtensions)) + { + rawUris = rawUris.SelectMany(uri => ApplyExtensions(sourceInfo, uri, settings.FileNameExtensions)); + } + + var testUris = rawUris.ToList(); + + foreach (var testUri in testUris) + { + var flag = testUri.IsFile ? DocumentAccessFlags.EnableFileLoading : DocumentAccessFlags.EnableWebLoading; + if (settings.AccessFlags.HasFlag(flag)) + { + var document = GetCachedDocument(testUri); + if (document != null) + { + return (document, null); + } + } + } + + var candidateUris = new List(); + + foreach (var testUri in testUris) + { + if (await IsCandidateUriAsync(settings, testUri).ConfigureAwait(false)) + { + candidateUris.Add(testUri); + } + } + + return (null, candidateUris); + } + + private static IEnumerable GetRawUris(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier) + { + Uri baseUri; + Uri uri; + + if (sourceInfo.HasValue && SpecifierMayBeRelative(settings, specifier)) + { + baseUri = GetBaseUri(sourceInfo.Value); + if ((baseUri != null) && Uri.TryCreate(baseUri, specifier, out uri)) + { + yield return uri; + } + } + + var searchPath = settings.SearchPath; + if (!string.IsNullOrWhiteSpace(searchPath)) + { + foreach (var url in searchPath.SplitSearchPath()) + { + if (Uri.TryCreate(url, UriKind.Absolute, out baseUri) && TryCombineSearchUri(baseUri, specifier, out uri)) + { + yield return uri; + } + } + } + + if (MiscHelpers.Try(out var path, () => Path.Combine(Directory.GetCurrentDirectory(), specifier)) && Uri.TryCreate(path, UriKind.Absolute, out uri)) + { + yield return uri; + } + + if (MiscHelpers.Try(out path, () => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, specifier)) && Uri.TryCreate(path, UriKind.Absolute, out uri)) + { + yield return uri; + } + + using (var process = Process.GetCurrentProcess()) + { + var module = process.MainModule; + if ((module != null) && Uri.TryCreate(module.FileName, UriKind.Absolute, out baseUri) && Uri.TryCreate(baseUri, specifier, out uri)) + { + yield return uri; + } + } + } + + private static IEnumerable ApplyExtensions(DocumentInfo? sourceInfo, Uri uri, string extensions) + { + yield return uri; + + var builder = new UriBuilder(uri); + var path = builder.Path; + + if (!string.IsNullOrEmpty(Path.GetFileName(path))) + { + var existingExtension = Path.GetExtension(path); + var compatibleExtensions = GetCompatibleExtensions(sourceInfo, extensions).ToList(); + + if (!compatibleExtensions.Contains(existingExtension, StringComparer.OrdinalIgnoreCase)) + { + foreach (var compatibleExtension in compatibleExtensions) + { + builder.Path = Path.ChangeExtension(path, existingExtension + compatibleExtension); + yield return builder.Uri; + } + } + } + } + + private static IEnumerable GetCompatibleExtensions(DocumentInfo? sourceInfo, string extensions) + { + string sourceExtension = null; + + if (sourceInfo.HasValue) + { + sourceExtension = Path.GetExtension((sourceInfo.Value.Uri != null) ? new UriBuilder(sourceInfo.Value.Uri).Path : sourceInfo.Value.Name); + if (!string.IsNullOrEmpty(sourceExtension)) + { + yield return sourceExtension; + } + } + + foreach (var extension in extensions.SplitSearchPath()) + { + var tempExtension = extension.StartsWith(".", StringComparison.Ordinal) ? extension : "." + extension; + if (!tempExtension.Equals(sourceExtension, StringComparison.OrdinalIgnoreCase)) + { + yield return tempExtension; + } + } + } + + private static bool SpecifierMayBeRelative(DocumentSettings settings, string specifier) + { + return !settings.AccessFlags.HasFlag(DocumentAccessFlags.EnforceRelativePrefix) || relativePrefixes.Any(specifier.StartsWith); + } + + private static Uri GetBaseUri(DocumentInfo sourceInfo) + { + var sourceUri = sourceInfo.Uri; + + if ((sourceUri == null) && !Uri.TryCreate(sourceInfo.Name, UriKind.RelativeOrAbsolute, out sourceUri)) + { + return null; + } + + if (!sourceUri.IsAbsoluteUri) + { + return null; + } + + return sourceUri; + } + + private static bool TryCombineSearchUri(Uri searchUri, string specifier, out Uri uri) + { + var searchUrl = searchUri.AbsoluteUri; + if (!searchUrl.EndsWith("/", StringComparison.Ordinal)) + { + searchUri = new Uri(searchUrl + "/"); + } + + return Uri.TryCreate(searchUri, specifier, out uri); + } + + private async Task IsCandidateUriAsync(DocumentSettings settings, Uri uri) + { + return uri.IsFile ? + settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableFileLoading) && await FileDocumentExistsAsync(uri.LocalPath).ConfigureAwait(false) : + settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableWebLoading) && await WebDocumentExistsAsync(uri).ConfigureAwait(false); + } + + private Task FileDocumentExistsAsync(string path) + { + Interlocked.Increment(ref fileCheckCount); + return Task.FromResult(File.Exists(path)); + } + + private async Task WebDocumentExistsAsync(Uri uri) + { + Interlocked.Increment(ref webCheckCount); + using (var client = new HttpClient()) + { + using (var request = new HttpRequestMessage(HttpMethod.Head, uri)) + { + try + { + using (var response = await client.SendAsync(request).ConfigureAwait(false)) + { + return response.IsSuccessStatusCode; + } + } + catch (HttpRequestException) + { + return false; + } + } + } + } + + private async Task LoadDocumentAsync(DocumentSettings settings, Uri uri, DocumentCategory category, DocumentContextCallback contextCallback) + { + if (uri.IsFile) + { + if (!settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableFileLoading)) + { + throw new UnauthorizedAccessException("The script engine is not configured for loading documents from the file system"); + } + } + else + { + if (!settings.AccessFlags.HasFlag(DocumentAccessFlags.EnableWebLoading)) + { + throw new UnauthorizedAccessException("The script engine is not configured for downloading documents from the Web"); + } + } + + var cachedDocument = GetCachedDocument(uri); + if (cachedDocument != null) + { + return cachedDocument; + } + + string contents; + + if (uri.IsFile) + { + using (var reader = new StreamReader(uri.LocalPath)) + { + contents = await reader.ReadToEndAsync().ConfigureAwait(false); + } + } + else + { + using (var client = new HttpClient()) + { + contents = await client.GetStringAsync(uri).ConfigureAwait(false); + } + } + + var documentInfo = new DocumentInfo(uri) { Category = category, ContextCallback = contextCallback }; + + if (!settings.AccessFlags.HasFlag(DocumentAccessFlags.UseAsyncLoadCallback)) + { + var callback = settings.LoadCallback; + callback?.Invoke(ref documentInfo); + } + else + { + var callback = settings.AsyncLoadCallback; + if (callback != null) + { + var documentInfoRef = ValueRef.Create(documentInfo); + await callback(documentInfoRef, new MemoryStream(Encoding.UTF8.GetBytes(contents), false)).ConfigureAwait(false); + documentInfo = documentInfoRef.Value; + } + } + + var document = CacheDocument(new StringDocument(documentInfo, contents), false); + + var expectedCategory = category ?? DocumentCategory.Script; + if (!settings.AccessFlags.HasFlag(DocumentAccessFlags.AllowCategoryMismatch) && (documentInfo.Category != expectedCategory)) + { + throw new FileLoadException($"Document category mismatch: '{expectedCategory}' expected, '{documentInfo.Category}' loaded", uri.IsFile ? uri.LocalPath : uri.AbsoluteUri); + } + + return document; + } + + #region DocumentLoader overrides + + /// + public override uint MaxCacheSize { get; set; } = 1024; + + /// + public override async Task LoadDocumentAsync(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonNullArgument(settings, nameof(settings)); + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + + if ((settings.AccessFlags & DocumentAccessFlags.EnableAllLoading) == DocumentAccessFlags.None) + { + throw new UnauthorizedAccessException("The script engine is not configured for loading documents"); + } + + if (category == null) + { + category = sourceInfo.HasValue ? sourceInfo.Value.Category : DocumentCategory.Script; + } + + (Document Document, List CandidateUris) result; + + if (Uri.TryCreate(specifier, UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri) + { + result = await GetCachedDocumentOrCandidateUrisAsync(settings, sourceInfo, uri).ConfigureAwait(false); + } + else + { + result = await GetCachedDocumentOrCandidateUrisAsync(settings, sourceInfo, specifier).ConfigureAwait(false); + } + + if (result.Document != null) + { + return result.Document; + } + + if (result.CandidateUris.Count < 1) + { + throw new FileNotFoundException(null, specifier); + } + + if (result.CandidateUris.Count == 1) + { + return await LoadDocumentAsync(settings, result.CandidateUris[0], category, contextCallback).ConfigureAwait(false); + } + + var exceptions = new List(result.CandidateUris.Count); + + foreach (var candidateUri in result.CandidateUris) + { + var task = LoadDocumentAsync(settings, candidateUri, category, contextCallback); + try + { + return await task.ConfigureAwait(false); + } + catch (Exception exception) + { + if ((task.Exception != null) && task.Exception.InnerExceptions.Count == 1) + { + Debug.Assert(ReferenceEquals(task.Exception.InnerExceptions[0], exception)); + exceptions.Add(exception); + } + else + { + exceptions.Add(task.Exception); + } + } + } + + if (exceptions.Count < 1) + { + MiscHelpers.AssertUnreachable(); + throw new FileNotFoundException(null, specifier); + } + + if (exceptions.Count == 1) + { + MiscHelpers.AssertUnreachable(); + throw new FileLoadException(exceptions[0].Message, specifier, exceptions[0]); + } + + throw new AggregateException(exceptions).Flatten(); + } + + /// + public override Document GetCachedDocument(Uri uri) + { + lock (cache) + { + for (var index = 0; index < cache.Count; index++) + { + var cachedDocument = cache[index]; + if (cachedDocument.Info.Uri == uri) + { + cache.RemoveAt(index); + cache.Insert(0, cachedDocument); + return cachedDocument; + } + } + + return null; + } + } + + /// + public override Document CacheDocument(Document document, bool replace) + { + MiscHelpers.VerifyNonNullArgument(document, nameof(document)); + if ((document.Info.Uri == null) || !document.Info.Uri.IsAbsoluteUri) + { + throw new ArgumentException("The document must have an absolute URI"); + } + + lock (cache) + { + for (var index = 0; index < cache.Count;) + { + var cachedDocument = cache[index]; + if (cachedDocument.Info.Uri != document.Info.Uri) + { + index++; + } + else + { + if (!replace) + { + Debug.Assert(cachedDocument.Contents.ReadToEnd().SequenceEqual(document.Contents.ReadToEnd())); + return cachedDocument; + } + + cache.RemoveAt(index); + } + } + + var maxCacheSize = Math.Max(16, Convert.ToInt32(Math.Min(MaxCacheSize, int.MaxValue))); + while (cache.Count >= maxCacheSize) + { + cache.RemoveAt(cache.Count - 1); + } + + cache.Insert(0, document); + return document; + } + } + + /// + public override void DiscardCachedDocuments() + { + lock (cache) + { + cache.Clear(); + } + } + + #endregion + + #region IStatistics implementation + + long IStatistics.FileCheckCount => Interlocked.Read(ref fileCheckCount); + + long IStatistics.WebCheckCount => Interlocked.Read(ref webCheckCount); + + void IStatistics.ResetCheckCounts() + { + Interlocked.Exchange(ref fileCheckCount, 0); + Interlocked.Exchange(ref webCheckCount, 0); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/DefaultDocumentLoader.cs.meta b/Unity/Package/Runtime/DefaultDocumentLoader.cs.meta new file mode 100644 index 000000000..483a4ab91 --- /dev/null +++ b/Unity/Package/Runtime/DefaultDocumentLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fc315e6940f9d94f9b0a73ed700c4cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs b/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs new file mode 100644 index 000000000..d3a4570f3 --- /dev/null +++ b/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies defaults for how type members are to be exposed to script code. + /// + /// + /// This attribute is applicable to classes, enums, interfaces, structs, and assemblies. Use + /// , , or + /// to override it for individual type members. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Assembly)] + public class DefaultScriptUsageAttribute : Attribute + { + /// + /// Initializes a new instance. + /// + public DefaultScriptUsageAttribute() + { + } + + /// + /// Initializes a new instance with the specified default script access setting. + /// + /// The default script access setting for type members. + public DefaultScriptUsageAttribute(ScriptAccess access) + { + Access = access; + } + + /// + /// Gets the default script access setting for type members. + /// + public ScriptAccess Access { get; } + } +} diff --git a/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs.meta b/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs.meta new file mode 100644 index 000000000..1354be157 --- /dev/null +++ b/Unity/Package/Runtime/DefaultScriptUsageAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 400f4a945a317174c9c34d2c26ed1d8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DelegateFactory.Generated.cs b/Unity/Package/Runtime/DelegateFactory.Generated.cs new file mode 100644 index 000000000..607d8a7fb --- /dev/null +++ b/Unity/Package/Runtime/DelegateFactory.Generated.cs @@ -0,0 +1,2491 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + + + +using System; +using System.Reflection; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.ClearScript +{ + internal static partial class DelegateFactory + { + private const int maxArgCount = 16; + + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = true; + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget() + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction()); + } + else + { + Invoke(() => ((dynamic)target)()); + } + } + else + { + + try + { + Invoke(() => ((dynamic)target)()); + } + finally + { + + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1)); + } + else + { + Invoke(() => ((dynamic)target)(a1)); + } + } + else + { + var v1 = GetArgValue(a1); + try + { + Invoke(() => ((dynamic)target)(ref v1)); + } + finally + { + SetArgValue(a1, v1); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + var v15 = GetArgValue(a15); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + SetArgValue(a15, v15); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class ProcShim : ProcShim + { + private static readonly MethodInfo method = typeof(ProcShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16)); + private readonly object target; + private readonly Delegate del; + + public ProcShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public void InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15, T16 a16) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + Invoke(() => scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)); + } + else + { + Invoke(() => ((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)); + } + } + else + { + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + var v15 = GetArgValue(a15); + var v16 = GetArgValue(a16); + try + { + Invoke(() => ((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15, ref v16)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + SetArgValue(a15, v15); + SetArgValue(a16, v16); + } + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = true; + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget() + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction()); + } + + return Invoke(() => (TResult)((dynamic)target)()); + } + + + try + { + return Invoke(() => (TResult)((dynamic)target)()); + } + finally + { + + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1)); + } + + var v1 = GetArgValue(a1); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1)); + } + finally + { + SetArgValue(a1, v1); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + var v15 = GetArgValue(a15); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + SetArgValue(a15, v15); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + [ExcludeFromCodeCoverage] + private class FuncShim : FuncShim + { + private static readonly MethodInfo method = typeof(FuncShim).GetMethod("InvokeTarget"); + private static readonly bool allByValue = GetAllByValue(typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16)); + private readonly object target; + private readonly Delegate del; + + public FuncShim(ScriptEngine engine, object target) + : base(engine) + { + this.target = GetCompatibleTarget(typeof(TDelegate), target); + del = Delegate.CreateDelegate(typeof(TDelegate), this, method); + } + + // ReSharper disable UnusedMember.Local + + public TResult InvokeTarget(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, T15 a15, T16 a16) + { + if (allByValue || Engine.EnableAutoHostVariables) + { + if (target is ScriptObject scriptObject) + { + return Invoke(() => (TResult)scriptObject.InvokeAsFunction(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)); + } + + return Invoke(() => (TResult)((dynamic)target)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)); + } + + var v1 = GetArgValue(a1); + var v2 = GetArgValue(a2); + var v3 = GetArgValue(a3); + var v4 = GetArgValue(a4); + var v5 = GetArgValue(a5); + var v6 = GetArgValue(a6); + var v7 = GetArgValue(a7); + var v8 = GetArgValue(a8); + var v9 = GetArgValue(a9); + var v10 = GetArgValue(a10); + var v11 = GetArgValue(a11); + var v12 = GetArgValue(a12); + var v13 = GetArgValue(a13); + var v14 = GetArgValue(a14); + var v15 = GetArgValue(a15); + var v16 = GetArgValue(a16); + try + { + return Invoke(() => (TResult)((dynamic)target)(ref v1, ref v2, ref v3, ref v4, ref v5, ref v6, ref v7, ref v8, ref v9, ref v10, ref v11, ref v12, ref v13, ref v14, ref v15, ref v16)); + } + finally + { + SetArgValue(a1, v1); + SetArgValue(a2, v2); + SetArgValue(a3, v3); + SetArgValue(a4, v4); + SetArgValue(a5, v5); + SetArgValue(a6, v6); + SetArgValue(a7, v7); + SetArgValue(a8, v8); + SetArgValue(a9, v9); + SetArgValue(a10, v10); + SetArgValue(a11, v11); + SetArgValue(a12, v12); + SetArgValue(a13, v13); + SetArgValue(a14, v14); + SetArgValue(a15, v15); + SetArgValue(a16, v16); + } + } + + // ReSharper restore UnusedMember.Local + + #region DelegateShim overrides + + public override Delegate Delegate + { + get { return del; } + } + + #endregion + } + + private static readonly Type[] procTemplates = + { + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + typeof(Action), + + }; + + private static readonly Type[] funcTemplates = + { + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + typeof(Func), + + }; + + private static readonly Type[] procShimTemplates = + { + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + typeof(ProcShim), + + }; + + private static readonly Type[] funcShimTemplates = + { + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + typeof(FuncShim), + + }; + } +} diff --git a/Unity/Package/Runtime/DelegateFactory.Generated.cs.meta b/Unity/Package/Runtime/DelegateFactory.Generated.cs.meta new file mode 100644 index 000000000..fa2fda7fc --- /dev/null +++ b/Unity/Package/Runtime/DelegateFactory.Generated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11db61cf3fae4fc40b129e2d35a4db2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DelegateFactory.cs b/Unity/Package/Runtime/DelegateFactory.cs new file mode 100644 index 000000000..047429dd7 --- /dev/null +++ b/Unity/Package/Runtime/DelegateFactory.cs @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal static partial class DelegateFactory + { + public static Delegate CreateProc(ScriptEngine engine, object target, int argCount) + { + if ((argCount < 0) || (argCount > maxArgCount)) + { + throw new ArgumentException("Invalid argument count", nameof(argCount)); + } + + var typeArgs = Enumerable.Repeat(typeof(object), argCount).ToArray(); + return CreateDelegate(engine, target, procTemplates[argCount].MakeSpecificType(typeArgs)); + } + + public static Delegate CreateFunc(ScriptEngine engine, object target, int argCount) + { + if ((argCount < 0) || (argCount > maxArgCount)) + { + throw new ArgumentException("Invalid argument count", nameof(argCount)); + } + + var typeArgs = Enumerable.Repeat(typeof(object), argCount).Concat(typeof(TResult).ToEnumerable()).ToArray(); + return CreateDelegate(engine, target, funcTemplates[argCount].MakeSpecificType(typeArgs)); + } + + public static TDelegate CreateDelegate(ScriptEngine engine, object target) + { + return (TDelegate)(object)CreateDelegate(engine, target, typeof(TDelegate)); + } + + public static Delegate CreateDelegate(ScriptEngine engine, object target, Type delegateType) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + if (!typeof(Delegate).IsAssignableFrom(delegateType)) + { + throw new ArgumentException("Invalid delegate type"); + } + + var method = delegateType.GetMethod("Invoke"); + if (method == null) + { + throw new ArgumentException("Invalid delegate type (invocation method not found)"); + } + + var parameters = method.GetParameters(); + if (parameters.Length > maxArgCount) + { + throw new ArgumentException("Invalid delegate type (parameter count too large)"); + } + + var paramTypes = parameters.Select(param => param.ParameterType).ToArray(); + if (paramTypes.Any(paramType => paramType.IsByRef)) + { + return CreateComplexDelegate(engine, target, delegateType); + } + + return CreateSimpleDelegate(engine, target, delegateType); + } + + private static Delegate CreateSimpleDelegate(ScriptEngine engine, object target, Type delegateType) + { + var method = delegateType.GetMethod("Invoke"); + var paramTypes = method.GetParameters().Select(param => param.ParameterType).ToArray(); + + Type shimType; + if (method.ReturnType == typeof(void)) + { + var typeArgs = paramTypes.Concat(delegateType.ToEnumerable()).ToArray(); + shimType = procShimTemplates[paramTypes.Length].MakeSpecificType(typeArgs); + } + else + { + var typeArgs = paramTypes.Concat(new[] { method.ReturnType, delegateType }).ToArray(); + shimType = funcShimTemplates[paramTypes.Length].MakeSpecificType(typeArgs); + } + + var shim = (DelegateShim)shimType.CreateInstance(engine, target); + return shim.Delegate; + } + + private static Delegate CreateComplexDelegate(ScriptEngine engine, object target, Type delegateType) + { + var method = delegateType.GetMethod("Invoke"); + + var parameters = method.GetParameters(); + var paramTypes = parameters.Select(param => param.ParameterType).ToArray(); + + var innerParamTypes = new Type[parameters.Length]; + for (var index = 0; index < parameters.Length; index++) + { + var paramType = paramTypes[index]; + if (parameters[index].IsOut) + { + innerParamTypes[index] = typeof(OutArg<>).MakeSpecificType(paramType.GetElementType()); + } + else if (paramType.IsByRef) + { + innerParamTypes[index] = typeof(RefArg<>).MakeSpecificType(paramType.GetElementType()); + } + else + { + innerParamTypes[index] = paramType; + } + } + + Type innerDelegateType; + if (method.ReturnType == typeof(void)) + { + innerDelegateType = procTemplates[innerParamTypes.Length].MakeSpecificType(innerParamTypes); + } + else + { + var typeArgs = innerParamTypes.Concat(method.ReturnType.ToEnumerable()).ToArray(); + innerDelegateType = funcTemplates[innerParamTypes.Length].MakeSpecificType(typeArgs); + } + + var paramExprs = paramTypes.Select((paramType, index) => Expression.Parameter(paramType, "a" + index)).ToArray(); + var varExprs = innerParamTypes.Select((paramType, index) => Expression.Variable(paramType, "v" + index)).ToArray(); + + var topExprs = new List(); + for (var index = 0; index < varExprs.Length; index++) + { + if (paramTypes[index].IsByRef) + { + var constructor = innerParamTypes[index].GetConstructor(new[] { paramTypes[index].GetElementType() }); + topExprs.Add(Expression.Assign(varExprs[index], Expression.New(constructor, paramExprs[index]))); + } + else + { + topExprs.Add(Expression.Assign(varExprs[index], paramExprs[index])); + } + } + + var innerDelegate = CreateSimpleDelegate(engine, target, innerDelegateType); + + // ReSharper disable once CoVariantArrayConversion + var invokeExpr = Expression.Invoke(Expression.Constant(innerDelegate), varExprs); + + var finallyExprs = new List(); + for (var index = 0; index < varExprs.Length; index++) + { + if (paramTypes[index].IsByRef) + { + var member = innerParamTypes[index].GetProperty("Value"); + var resultExpr = Expression.MakeMemberAccess(varExprs[index], member); + finallyExprs.Add(Expression.Assign(paramExprs[index], resultExpr)); + } + } + + var finallyBlockExpr = Expression.Block(finallyExprs); + topExprs.Add(Expression.TryFinally(invokeExpr, finallyBlockExpr)); + + var topBlockExpr = Expression.Block(method.ReturnType, varExprs, topExprs); + return Expression.Lambda(delegateType, topBlockExpr, paramExprs).Compile(); + } + + private abstract class DelegateShim + { + public abstract Delegate Delegate { get; } + + protected ScriptEngine Engine { get; } + + protected DelegateShim(ScriptEngine engine) + { + Engine = engine; + } + + protected static bool GetAllByValue(params Type[] types) + { + return !types.Any(type => typeof(IByRefArg).IsAssignableFrom(type)); + } + + protected static object GetArgValue(object arg) + { + return (arg is IByRefArg byRefArg) ? byRefArg.Value : arg; + } + + protected static void SetArgValue(object arg, object value) + { + if (arg is IByRefArg byRefArg) + { + byRefArg.Value = value; + } + } + + protected static object GetCompatibleTarget(Type delegateType, object target) + { + if ((target is Delegate del) && (del.GetType() != delegateType)) + { + // The target is a delegate of a different type from the one we are creating. + // Normally we expect the target to be a script function (COM object), but + // since we'll be invoking it dynamically, there's no need to restrict it. + // However, if the target is a delegate of a type that's inaccessible to this + // assembly, dynamic invocation fails. Strangely, delegate type accessibility + // doesn't seem to affect delegate creation, so we can work around this by + // creating a compatible delegate based on the properties of the target. + + return Delegate.CreateDelegate(delegateType, del.Target, del.Method); + } + + return target; + } + } + + private abstract class ProcShim : DelegateShim + { + private readonly Action invoker; + + protected ProcShim(ScriptEngine engine) + : base(engine) + { + if (engine == null) + { + invoker = action => action(); + } + else + { + invoker = engine.SyncInvoke; + } + } + + protected void Invoke(Action action) + { + invoker(action); + } + } + + private abstract class FuncShim : DelegateShim + { + private readonly Func, TResult> invoker; + + protected FuncShim(ScriptEngine engine) + : base(engine) + { + if (engine == null) + { + invoker = func => func(); + } + else + { + invoker = engine.SyncInvoke; + } + } + + protected TResult Invoke(Func func) + { + return invoker(func); + } + } + } +} diff --git a/Unity/Package/Runtime/DelegateFactory.cs.meta b/Unity/Package/Runtime/DelegateFactory.cs.meta new file mode 100644 index 000000000..47e89eaf6 --- /dev/null +++ b/Unity/Package/Runtime/DelegateFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45876a06a0849cb4aa6f9ee41b778ff3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Document.cs b/Unity/Package/Runtime/Document.cs new file mode 100644 index 000000000..bc9396117 --- /dev/null +++ b/Unity/Package/Runtime/Document.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.IO; +using System.Text; + +namespace Microsoft.ClearScript +{ + /// + /// Provides an abstract representation of a document. + /// + public abstract class Document + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + protected Document() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + /// + /// Gets a structure containing meta-information for the document. + /// + public abstract DocumentInfo Info { get; } + + /// + /// Gets a stream that provides read access to the document. + /// + public abstract Stream Contents { get; } + + /// + /// Gets the document's character encoding. + /// + /// + /// This property returns null if the document contains binary data or if its + /// character encoding is unknown. + /// + public virtual Encoding Encoding => null; + } +} diff --git a/Unity/Package/Runtime/Document.cs.meta b/Unity/Package/Runtime/Document.cs.meta new file mode 100644 index 000000000..5a22e7cc1 --- /dev/null +++ b/Unity/Package/Runtime/Document.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4b5847f578efb041b56d6e5ed3c73f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentAccessFlags.cs b/Unity/Package/Runtime/DocumentAccessFlags.cs new file mode 100644 index 000000000..de97f7ad9 --- /dev/null +++ b/Unity/Package/Runtime/DocumentAccessFlags.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Defines document access options. + /// + [Flags] + public enum DocumentAccessFlags + { + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that documents may be loaded from the file system. + /// + EnableFileLoading = 0x00000001, + + /// + /// Specifies that documents may be downloaded from the Web. + /// + EnableWebLoading = 0x00000002, + + /// + /// Specifies that documents may be loaded from any location. + /// + EnableAllLoading = EnableFileLoading | EnableWebLoading, + + /// + /// Specifies that a document path must begin with a segment of "." or ".." to be + /// considered a relative path. By default, any path that is not explicitly a top-level + /// or root path is eligible. + /// + EnforceRelativePrefix = 0x00000004, + + /// + /// Relaxes the requirement that a loaded document must be of the requested category. + /// + AllowCategoryMismatch = 0x00000008, + + /// + /// Enables the use of instead of . + /// + UseAsyncLoadCallback = 0x00000010 + } +} diff --git a/Unity/Package/Runtime/DocumentAccessFlags.cs.meta b/Unity/Package/Runtime/DocumentAccessFlags.cs.meta new file mode 100644 index 000000000..c8217afec --- /dev/null +++ b/Unity/Package/Runtime/DocumentAccessFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9b60963a293a8d47b657a67727998c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentCategory.cs b/Unity/Package/Runtime/DocumentCategory.cs new file mode 100644 index 000000000..e57313e1e --- /dev/null +++ b/Unity/Package/Runtime/DocumentCategory.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Represents a document category. + /// + public abstract class DocumentCategory + { + internal DocumentCategory() + { + MaxCacheSize = 1024; + } + + /// + /// Gets or sets the maximum cache size for the document category. + /// + /// + /// + /// This property specifies the maximum number of prepared or compiled documents of the + /// current category to be cached by script engines. Its initial value is 1024. + /// + /// + /// Each script engine or runtime maintains private caches for supported document + /// categories. These are distinct from the caches used by document loaders. + /// + /// + /// + public uint MaxCacheSize { get; set; } + + /// + /// Gets the document category for normal scripts. + /// + public static DocumentCategory Script => ScriptDocument.Instance; + + /// + /// Gets the document category for JSON documents. + /// + public static DocumentCategory Json => JsonDocument.Instance; + + internal abstract DocumentKind Kind { get; } + + internal abstract string DefaultName { get; } + + #region Nested type: ScriptDocument + + private sealed class ScriptDocument : DocumentCategory + { + public static readonly ScriptDocument Instance = new ScriptDocument(); + + private ScriptDocument() + { + } + + #region DocumentCategory overrides + + internal override DocumentKind Kind => DocumentKind.Script; + + internal override string DefaultName => "Script"; + + #endregion + + #region Object overrides + + public override string ToString() + { + return "Script"; + } + + #endregion + } + + #endregion + + #region Nested type: JsonDocument + + private sealed class JsonDocument : DocumentCategory + { + public static readonly JsonDocument Instance = new JsonDocument(); + + private JsonDocument() + { + } + + #region DocumentCategory overrides + + internal override DocumentKind Kind => DocumentKind.Json; + + internal override string DefaultName => "JSON"; + + #endregion + + #region Object overrides + + public override string ToString() + { + return "JSON Document"; + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/DocumentCategory.cs.meta b/Unity/Package/Runtime/DocumentCategory.cs.meta new file mode 100644 index 000000000..f8cb9e1de --- /dev/null +++ b/Unity/Package/Runtime/DocumentCategory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c1d9da2d8fb066429343651c1fcc513 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentContextCallback.cs b/Unity/Package/Runtime/DocumentContextCallback.cs new file mode 100644 index 000000000..69d720b61 --- /dev/null +++ b/Unity/Package/Runtime/DocumentContextCallback.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a method that retrieves context information for a document. + /// + /// A structure containing meta-information for the document. + /// A property collection containing context information for the document. + public delegate IDictionary DocumentContextCallback(DocumentInfo info); +} diff --git a/Unity/Package/Runtime/DocumentContextCallback.cs.meta b/Unity/Package/Runtime/DocumentContextCallback.cs.meta new file mode 100644 index 000000000..d40b4721e --- /dev/null +++ b/Unity/Package/Runtime/DocumentContextCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9abd60dbe6b99bf4c9a3ab6370e415d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentFlags.cs b/Unity/Package/Runtime/DocumentFlags.cs new file mode 100644 index 000000000..50db9f800 --- /dev/null +++ b/Unity/Package/Runtime/DocumentFlags.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Defines document attributes. + /// + [Flags] + public enum DocumentFlags + { + /// + /// Indicates that no attributes are present. + /// + None = 0, + + /// + /// Indicates that the document is temporary and can be discarded after use. Only Windows + /// Script engines honor this attribute. + /// + IsTransient = 0x00000001, + + /// + /// Specifies that the script engine is to wait for a debugger connection and schedule a + /// pause before executing the first line of the document. Windows Script engines do not + /// honor this attribute. For it to be effective, debugging features must be enabled, a + /// debugger must not already be connected, and the script engine must not already have + /// waited for a debugger connection. + /// + AwaitDebuggerAndPause = 0x00000002 + } +} diff --git a/Unity/Package/Runtime/DocumentFlags.cs.meta b/Unity/Package/Runtime/DocumentFlags.cs.meta new file mode 100644 index 000000000..3d0da8964 --- /dev/null +++ b/Unity/Package/Runtime/DocumentFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0c90eda8430d0e4ca1f73039d56347a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentInfo.cs b/Unity/Package/Runtime/DocumentInfo.cs new file mode 100644 index 000000000..218da5e33 --- /dev/null +++ b/Unity/Package/Runtime/DocumentInfo.cs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Threading; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Contains meta-information for a document. + /// + public struct DocumentInfo + { + private static long lastUniqueId; + + private readonly string name; + private DocumentCategory category; + private ulong uniqueId; + + /// + /// Initializes a new structure with the specified document name. + /// + /// The document name. + public DocumentInfo(string name) + : this() + { + this.name = name; + uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned(); + } + + /// + /// Initializes a new structure with the specified document URI. + /// + /// The document URI. + public DocumentInfo(Uri uri) + : this() + { + MiscHelpers.VerifyNonNullArgument(uri, nameof(uri)); + Uri = uri.IsAbsoluteUri ? uri : new Uri(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + uri); + name = Path.GetFileName(Uri.AbsolutePath); + uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned(); + } + + /// + /// Gets the document's name. + /// + /// + /// This property always returns a non-blank string. If a null or blank document name was + /// specified at instantiation time, this property returns a default document name. + /// + public string Name => MiscHelpers.EnsureNonBlank(name, Category.DefaultName); + + /// + /// Gets the document's URI. + /// + /// + /// This property returns null if a URI was not specified at instantiation time. + /// + public Uri Uri { get; } + + /// + /// Gets or sets an optional source map URI for the document. + /// + public Uri SourceMapUri { get; set; } + + /// + /// Gets or sets the document's category. + /// + public DocumentCategory Category + { + get => category ?? DocumentCategory.Script; + set => category = value; + } + + /// + /// Gets or sets optional document attributes. + /// + public DocumentFlags? Flags { get; set; } + + /// + /// Gets or sets an optional context callback for the document. + /// + /// + /// + /// This property currently applies only to modules. If specified, the callback is invoked + /// the first time the module attempts to retrieve its context information. The properties + /// it returns are made available to the module implementation. This mechanism can be used + /// to expose host resources selectively, securely, and without polluting the script + /// engine's global namespace. + /// + /// + /// Use + /// import.meta + /// to access the context information of a JavaScript + /// module. In a module, use module.meta. + /// + /// + public DocumentContextCallback ContextCallback { get; set; } + + internal UniqueDocumentInfo MakeUnique(ScriptEngine engine) + { + return MakeUnique(engine.DocumentNameManager); + } + + internal UniqueDocumentInfo MakeUnique(ScriptEngine engine, DocumentFlags? defaultFlags) + { + return MakeUnique(engine.DocumentNameManager, defaultFlags); + } + + internal UniqueDocumentInfo MakeUnique(IUniqueNameManager manager) + { + return MakeUnique(manager, null); + } + + internal UniqueDocumentInfo MakeUnique(IUniqueNameManager manager, DocumentFlags? defaultFlags) + { + var info = this; + if (!info.Flags.HasValue && defaultFlags.HasValue) + { + info.Flags = defaultFlags; + } + + if (uniqueId < 1) + { + uniqueId = Interlocked.Increment(ref lastUniqueId).ToUnsigned(); + } + + var uniqueName = manager.GetUniqueName(Name, Category.DefaultName); + if (info.Flags.GetValueOrDefault().HasFlag(DocumentFlags.IsTransient)) + { + uniqueName += " [temp]"; + } + + return new UniqueDocumentInfo(info, uniqueId, uniqueName); + } + } +} diff --git a/Unity/Package/Runtime/DocumentInfo.cs.meta b/Unity/Package/Runtime/DocumentInfo.cs.meta new file mode 100644 index 000000000..2a3ab06ff --- /dev/null +++ b/Unity/Package/Runtime/DocumentInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 09b88b2ff9e34ab4da4ea9929c17e5f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentKind.cs b/Unity/Package/Runtime/DocumentKind.cs new file mode 100644 index 000000000..5c14023ef --- /dev/null +++ b/Unity/Package/Runtime/DocumentKind.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + internal enum DocumentKind + { + // IMPORTANT: maintain bitwise equivalence with native enum DocumentKind + Script, + JavaScriptModule, + CommonJSModule, + Json + } +} diff --git a/Unity/Package/Runtime/DocumentKind.cs.meta b/Unity/Package/Runtime/DocumentKind.cs.meta new file mode 100644 index 000000000..c530a7619 --- /dev/null +++ b/Unity/Package/Runtime/DocumentKind.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 381a3143157f4754c84dbb827b936db7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentLoadCallback.cs b/Unity/Package/Runtime/DocumentLoadCallback.cs new file mode 100644 index 000000000..6a59dfc7d --- /dev/null +++ b/Unity/Package/Runtime/DocumentLoadCallback.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Represents a method to be called when a document is loaded. + /// + /// A structure containing meta-information for the document. + /// + /// The callback can modify the document meta-information by specifying or overriding any of + /// its mutable properties. + /// + public delegate void DocumentLoadCallback(ref DocumentInfo info); +} diff --git a/Unity/Package/Runtime/DocumentLoadCallback.cs.meta b/Unity/Package/Runtime/DocumentLoadCallback.cs.meta new file mode 100644 index 000000000..16698ed62 --- /dev/null +++ b/Unity/Package/Runtime/DocumentLoadCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07806adca96899249addfda4abb2740e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentLoader.cs b/Unity/Package/Runtime/DocumentLoader.cs new file mode 100644 index 000000000..ed24d24f4 --- /dev/null +++ b/Unity/Package/Runtime/DocumentLoader.cs @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.ClearScript.Util; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a document loader. + /// + public abstract class DocumentLoader + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + protected DocumentLoader() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + /// + /// Gets the default document loader. + /// + public static DocumentLoader Default => DefaultImpl.Instance; + + /// + /// Gets or sets the maximum size of the document loader's cache. + /// + /// + /// This property specifies the maximum number of documents to be cached by the document + /// loader. For the default document loader, its initial value is 1024. + /// + /// + public virtual uint MaxCacheSize + { + get => 0; + set => throw new NotSupportedException("The document loader does not support caching"); + } + + /// + /// Loads a document. + /// + /// Document access settings for the operation. + /// An optional structure containing meta-information for the requesting document. + /// A string specifying the document to be loaded. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// A instance that represents the loaded document. + /// + /// A loaded document must have an absolute URI. Once a + /// load operation has completed successfully, subsequent requests that resolve to the same + /// URI are expected to return the same reference, although loaders + /// are not required to manage document caches of unlimited size. + /// + public virtual Document LoadDocument(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + + try + { + return LoadDocumentAsync(settings, sourceInfo, specifier, category, contextCallback).Result; + } + catch (AggregateException exception) + { + exception = exception.Flatten(); + if (exception.InnerExceptions.Count == 1) + { + throw new FileLoadException(null, specifier, exception.InnerExceptions[0]); + } + + throw new FileLoadException(null, specifier, exception); + } + } + + /// + /// Loads a document asynchronously. + /// + /// Document access settings for the operation. + /// An optional structure containing meta-information for the requesting document. + /// A string specifying the document to be loaded. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// A task that represents the asynchronous operation. Upon completion, the task's result is a instance that represents the loaded document. + /// + /// A loaded document must have an absolute URI. Once a + /// load operation has completed successfully, subsequent requests that resolve to the same + /// URI are expected to return the same reference, although loaders + /// are not required to manage document caches of unlimited size. + /// + public abstract Task LoadDocumentAsync(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback); + + /// + /// Searches for a cached document by URI. + /// + /// The document URI for which to search. + /// The cached document if it was found, null otherwise. + public virtual Document GetCachedDocument(Uri uri) + { + return null; + } + + /// + /// Stores a document in the cache. + /// + /// The document to store in the cache. + /// True to replace any existing document with the same URI, false otherwise. + /// The cached document, which may be different from if is false. + /// + /// A cached document must have an absolute URI. + /// + public virtual Document CacheDocument(Document document, bool replace) + { + throw new NotSupportedException("The document loader does not support caching"); + } + + /// + /// Discards all cached documents. + /// + public virtual void DiscardCachedDocuments() + { + } + + #region Nested type: IStatistics + + internal interface IStatistics + { + long FileCheckCount { get; } + long WebCheckCount { get; } + void ResetCheckCounts(); + } + + #endregion + + #region Nested type: DefaultImpl + + // IMPORTANT: Before its implementation was factored out and made public, some hosts used + // reflection to instantiate this class in order to maintain multiple document caches. It + // should therefore be treated and retained as part of the public API, as well as a + // placeholder for any future overrides of the default functionality. + + private sealed class DefaultImpl : DefaultDocumentLoader + { + public static readonly DefaultImpl Instance = new DefaultImpl(); + + private DefaultImpl() + { + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/DocumentLoader.cs.meta b/Unity/Package/Runtime/DocumentLoader.cs.meta new file mode 100644 index 000000000..6f6de04a9 --- /dev/null +++ b/Unity/Package/Runtime/DocumentLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 289e3a5519709de49abd61a4476f7123 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DocumentSettings.cs b/Unity/Package/Runtime/DocumentSettings.cs new file mode 100644 index 000000000..8b7c0672f --- /dev/null +++ b/Unity/Package/Runtime/DocumentSettings.cs @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Threading.Tasks; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a document access configuration. + /// + /// + /// This class can be extended to accommodate custom document loaders. + /// + public class DocumentSettings + { + private DocumentLoader loader; + private readonly ConcurrentDictionary, Document> systemDocumentMap = new ConcurrentDictionary, Document>(); + + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public DocumentSettings() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + /// + /// Gets or sets a document loader. + /// + public DocumentLoader Loader + { + get => loader ?? DocumentLoader.Default; + set => loader = value; + } + + /// + /// Gets or sets document access options. + /// + public DocumentAccessFlags AccessFlags { get; set; } + + /// + /// Gets or sets a semicolon-delimited list of directory URLs or paths to search for documents. + /// + public string SearchPath { get; set; } + + /// + /// Gets or sets a semicolon-delimited list of supported file name extensions. + /// + public string FileNameExtensions { get; set; } + + /// + /// Gets or set an optional method to be called when a document is loaded. + /// + public DocumentLoadCallback LoadCallback { get; set; } + + /// + /// Gets or set an optional method to be called asynchronously when a document is loaded. + /// + public AsyncDocumentLoadCallback AsyncLoadCallback { get; set; } + + /// + /// Gets or sets an optional document context callback. + /// + /// + /// + /// This property is used as an alternative to . + /// If specified, the callback is invoked the first time a module attempts to retrieve its + /// context information. The properties it returns are made available to the module + /// implementation. This mechanism can be used to expose host resources selectively, + /// securely, and without polluting the script engine's global namespace. + /// + /// + /// Use + /// import.meta + /// to access the context information of a JavaScript + /// module. In a module, use module.meta. + /// + /// + public DocumentContextCallback ContextCallback { get; set; } + + /// + /// Adds a system document to the configuration. + /// + /// An identifier for the document. + /// A string containing the document's contents. + /// + /// System documents take precedence over loaded documents. Once this method is invoked, + /// document access using this configuration will always map the combination of + /// and to the + /// specified document, bypassing the configuration's document loader. + /// + public void AddSystemDocument(string identifier, string contents) + { + AddSystemDocument(identifier, null, contents); + } + + /// + /// Adds a system document with the specified category to the configuration. + /// + /// An identifier for the document. + /// An optional category for the document. + /// A string containing the document's contents. + /// + /// System documents take precedence over loaded documents. Once this method is invoked, + /// document access using this configuration will always map the combination of + /// and to the specified + /// document, bypassing the configuration's document loader. + /// + public void AddSystemDocument(string identifier, DocumentCategory category, string contents) + { + AddSystemDocument(identifier, category, contents, null); + } + + /// + /// Adds a system document with the specified category and context callback to the configuration. + /// + /// An identifier for the document. + /// An optional category for the document. + /// A string containing the document's contents. + /// An optional context callback for the document. + /// + /// System documents take precedence over loaded documents. Once this method is invoked, + /// document access using this configuration will always map the combination of + /// and to the specified + /// document, bypassing the configuration's document loader. + /// + public void AddSystemDocument(string identifier, DocumentCategory category, string contents, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(identifier, nameof(identifier), "Invalid document specifier"); + var info = new DocumentInfo(Path.GetFileName(identifier)) { Category = category, ContextCallback = contextCallback }; + AddSystemDocument(identifier, new StringDocument(info, contents)); + } + + + /// + /// Adds the specified document as a system document to the configuration. + /// + /// An identifier for the document. + /// The document to be added as a system document. + /// + /// System documents take precedence over loaded documents. Once this method is invoked, + /// document access using this configuration will always map the combination of + /// and the specified document's category to the specified + /// document, bypassing the configuration's document loader. + /// + public void AddSystemDocument(string identifier, Document document) + { + MiscHelpers.VerifyNonNullArgument(document, nameof(document)); + systemDocumentMap[Tuple.Create(identifier, document.Info.Category)] = document; + } + + internal Document LoadDocument(DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + return FindSystemDocument(specifier, category) ?? Loader.LoadDocument(this, sourceInfo, specifier, category, contextCallback); + } + + internal async Task LoadDocumentAsync(DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + return FindSystemDocument(specifier, category) ?? await Loader.LoadDocumentAsync(this, sourceInfo, specifier, category, contextCallback).ConfigureAwait(false); + } + + private Document FindSystemDocument(string identifier, DocumentCategory category) + { + if (systemDocumentMap.TryGetValue(Tuple.Create(identifier, category ?? DocumentCategory.Script), out var document)) + { + return document; + } + + if (AccessFlags.HasFlag(DocumentAccessFlags.AllowCategoryMismatch)) + { + foreach (var pair in systemDocumentMap) + { + if (pair.Key.Item1 == identifier) + { + return pair.Value; + } + } + } + + return null; + } + } +} diff --git a/Unity/Package/Runtime/DocumentSettings.cs.meta b/Unity/Package/Runtime/DocumentSettings.cs.meta new file mode 100644 index 000000000..c7722f3d8 --- /dev/null +++ b/Unity/Package/Runtime/DocumentSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d483326a30d45a742b33e52d5141b77e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DynamicHostMetaObject.cs b/Unity/Package/Runtime/DynamicHostMetaObject.cs new file mode 100644 index 000000000..684175bd8 --- /dev/null +++ b/Unity/Package/Runtime/DynamicHostMetaObject.cs @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; +using System.Dynamic; + +namespace Microsoft.ClearScript +{ + internal sealed class DynamicHostMetaObject : DynamicMetaObject + { + private readonly IDynamicMetaObjectProvider metaObjectProvider; + private readonly DynamicMetaObject metaObject; + + public DynamicHostMetaObject(IDynamicMetaObjectProvider metaObjectProvider, DynamicMetaObject metaObject) + : base(metaObject.Expression, metaObject.Restrictions, metaObject.Value) + { + this.metaObjectProvider = metaObjectProvider; + this.metaObject = metaObject; + } + + public bool HasMember(string name, bool ignoreCase) + { + return DynamicHostObject.HasMember(metaObjectProvider, metaObject, name, ignoreCase); + } + + #region DynamicMetaObject overrides + + public override IEnumerable GetDynamicMemberNames() + { + return metaObject.GetDynamicMemberNames(); + } + + public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) + { + return metaObject.BindBinaryOperation(binder, arg); + } + + public override DynamicMetaObject BindConvert(ConvertBinder binder) + { + return metaObject.BindConvert(binder); + } + + public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) + { + return metaObject.BindCreateInstance(binder, args); + } + + public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) + { + return metaObject.BindDeleteIndex(binder, indexes); + } + + public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) + { + return metaObject.BindDeleteMember(binder); + } + + public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) + { + return metaObject.BindGetIndex(binder, indexes); + } + + public override DynamicMetaObject BindGetMember(GetMemberBinder binder) + { + return metaObject.BindGetMember(binder); + } + + public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) + { + return metaObject.BindInvoke(binder, args); + } + + public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) + { + return metaObject.BindInvokeMember(binder, args); + } + + public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) + { + return metaObject.BindSetIndex(binder, indexes, value); + } + + public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) + { + return metaObject.BindSetMember(binder, value); + } + + public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) + { + return metaObject.BindUnaryOperation(binder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/DynamicHostMetaObject.cs.meta b/Unity/Package/Runtime/DynamicHostMetaObject.cs.meta new file mode 100644 index 000000000..5cfca54be --- /dev/null +++ b/Unity/Package/Runtime/DynamicHostMetaObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9995339d7bb3107408815bf4ee56695f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/DynamicHostObject.cs b/Unity/Package/Runtime/DynamicHostObject.cs new file mode 100644 index 000000000..ab3407f14 --- /dev/null +++ b/Unity/Package/Runtime/DynamicHostObject.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Dynamic; +using System.Linq; + +namespace Microsoft.ClearScript +{ + /// + /// Extends for enhanced behavior and performance in a scripting environment. + /// + public abstract class DynamicHostObject : DynamicObject + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + protected DynamicHostObject() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + /// + /// Determines whether the object has the specified named member. + /// + /// The member name for which to search. + /// True to perform a case-insensitive search, false otherwise. + /// True if the named member was found, false otherwise. + public virtual bool HasMember(string name, bool ignoreCase) + { + var comparer = ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; + return GetDynamicMemberNames().Contains(name, comparer); + } + + internal static bool HasMember(IDynamicMetaObjectProvider metaObjectProvider, DynamicMetaObject metaObject, string name, bool ignoreCase) + { + if (metaObjectProvider is DynamicHostObject hostObject) + { + return hostObject.HasMember(name, ignoreCase); + } + + var comparer = ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; + return metaObject.GetDynamicMemberNames().Contains(name, comparer); + } + } +} diff --git a/Unity/Package/Runtime/DynamicHostObject.cs.meta b/Unity/Package/Runtime/DynamicHostObject.cs.meta new file mode 100644 index 000000000..a144f80a8 --- /dev/null +++ b/Unity/Package/Runtime/DynamicHostObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 352dbe3543e44cf488f5a06d021a5835 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ExtendedHostFunctions.cs b/Unity/Package/Runtime/ExtendedHostFunctions.cs new file mode 100644 index 000000000..54f190da6 --- /dev/null +++ b/Unity/Package/Runtime/ExtendedHostFunctions.cs @@ -0,0 +1,315 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript +{ + /// + /// Provides optional script-callable utility functions. This extended version allows script + /// code to import host types. + /// + public class ExtendedHostFunctions : HostFunctions + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public ExtendedHostFunctions() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + #region script-callable interface + + // ReSharper disable InconsistentNaming + + /// + /// Imports a host type by name. + /// + /// The fully qualified name of the host type to import. + /// Optional generic type arguments. + /// The imported host type. + /// + /// + /// Host types are imported in the form of objects whose properties and methods are bound + /// to the host type's static members and nested types. If refers + /// to a generic type, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see + /// AddHostObject. + /// + /// + /// + /// The following code imports the + /// Dictionary + /// generic type and uses it to create a string dictionary. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var DictT = host.type("System.Collections.Generic.Dictionary"); + /// var StringT = host.type("System.String"); + /// var dict = host.newObj(DictT(StringT, StringT)); + /// + /// Another way to create a string dictionary is to import the specific type directly. + /// + /// var StringT = host.type("System.String"); + /// var StringDictT = host.type("System.Collections.Generic.Dictionary", StringT, StringT); + /// var dict = host.newObj(StringDictT); + /// + /// + public object type(string name, params object[] hostTypeArgs) + { + return TypeHelpers.ImportType(name, null, false, hostTypeArgs); + } + + /// + /// Imports a host type by name from the specified assembly. + /// + /// The fully qualified name of the host type to import. + /// The name of the assembly that contains the host type to import. + /// Optional generic type arguments. + /// The imported host type. + /// + /// + /// Host types are imported in the form of objects whose properties and methods are bound + /// to the host type's static members and nested types. If refers + /// to a generic type, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see + /// AddHostObject. + /// + /// + /// + /// The following code imports and uses it to create + /// an array of strings. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var EnumerableT = host.type("System.Linq.Enumerable", "System.Core"); + /// var Int32T = host.type("System.Int32"); + /// var StringT = host.type("System.String"); + /// var SelectorT = host.type("System.Func", Int32T, StringT); + /// var selector = host.del(SelectorT, function (num) { return StringT.Format("The number is {0}.", num); }); + /// var array = EnumerableT.Range(0, 5).Select(selector).ToArray(); + /// + /// + /// + public object type(string name, string assemblyName, params object[] hostTypeArgs) + { + return TypeHelpers.ImportType(name, assemblyName, true, hostTypeArgs); + } + + /// + /// Imports the host type for the specified . + /// + /// The that specifies the host type to import. + /// The imported host type. + /// + /// + /// Host types are imported in the form of objects whose properties and methods are bound + /// to the host type's static members and nested types. If refers + /// to a generic type, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see + /// AddHostObject. + /// + /// + public object type(Type type) + { + return HostType.Wrap(type); + } + + /// + /// Imports the host array type for the specified element type. + /// + /// The element type for the host array type to import. + /// The number of dimensions for the host array type to import. + /// The imported host array type. + public object arrType(int rank = 1) + { + return HostType.Wrap(typeof(T).MakeArrayType(rank)); + } + + /// + /// Imports types from one or more host assemblies. + /// + /// The names of the assemblies that contain the types to import. + /// The imported host type collection. + /// + /// Host type collections provide convenient scriptable access to all the types defined in one + /// or more host assemblies. They are hierarchical collections where leaf nodes represent types + /// and parent nodes represent namespaces. For example, if an assembly contains a type named + /// "Acme.Gadgets.Button", the corresponding collection will have a property named "Acme" whose + /// value is an object with a property named "Gadgets" whose value is an object with a property + /// named "Button" whose value represents the Acme.Gadgets.Button host type. + /// + /// + /// The following code imports types from several core assemblies and uses + /// to create an array of integers. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var clr = host.lib("mscorlib", "System", "System.Core"); + /// var array = clr.System.Linq.Enumerable.Range(0, 5).ToArray(); + /// + /// + public HostTypeCollection lib(params string[] assemblyNames) + { + return lib(null, assemblyNames); + } + + /// + /// Imports types from one or more host assemblies and merges them with an existing host type collection. + /// + /// The host type collection with which to merge types from the specified assemblies. + /// The names of the assemblies that contain the types to import. + /// A host type collection: if it is not null, a new host type collection otherwise. + /// + /// Host type collections provide convenient scriptable access to all the types defined in one + /// or more host assemblies. They are hierarchical collections where leaf nodes represent types + /// and parent nodes represent namespaces. For example, if an assembly contains a type named + /// "Acme.Gadgets.Button", the corresponding collection will have a property named "Acme" whose + /// value is an object with a property named "Gadgets" whose value is an object with a property + /// named "Button" whose value represents the Acme.Gadgets.Button host type. + /// + /// + /// The following code imports types from several core assemblies and uses + /// to create an array of integers. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var clr = host.lib("mscorlib"); + /// host.lib(clr, "System"); + /// host.lib(clr, "System.Core"); + /// var array = clr.System.Linq.Enumerable.Range(0, 5).ToArray(); + /// + /// + public HostTypeCollection lib(HostTypeCollection collection, params string[] assemblyNames) + { + var target = collection ?? new HostTypeCollection(); + Array.ForEach(assemblyNames, target.AddAssembly); + return target; + } + + /// + /// Imports a COM/ActiveX type. + /// + /// The programmatic identifier (ProgID) of the registered class to import. + /// An optional name that specifies the server from which to import the type. + /// The imported COM/ActiveX type. + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// The following code imports the + /// Scripting.Dictionary + /// class and uses it to create and populate an instance. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var DictT = host.comType('Scripting.Dictionary'); + /// var dict = host.newObj(DictT); + /// dict.Add('foo', 123); + /// dict.Add('bar', 456.789); + /// dict.Add('baz', 'abc'); + /// + /// + public object comType(string progID, string serverName = null) + { + return HostType.Wrap(MiscHelpers.GetCOMType(progID, serverName)); + } + + /// + /// Creates a COM/ActiveX object of the specified type. + /// + /// The programmatic identifier (ProgID) of the registered class to instantiate. + /// An optional name that specifies the server on which to create the object. + /// A new COM/ActiveX object of the specified type. + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// The following code creates a + /// Scripting.FileSystemObject + /// instance and uses it to list the drives on the local machine. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var fso = host.newComObj('Scripting.FileSystemObject'); + /// var ConsoleT = host.type('System.Console'); + /// for (en = fso.Drives.GetEnumerator(); en.MoveNext();) { + /// ConsoleT.WriteLine(en.Current.Path); + /// } + /// + /// + public object newComObj(string progID, string serverName = null) + { + return MiscHelpers.CreateCOMObject(progID, serverName); + } + + /// + /// Imports enumerations defined within or referenced from a COM/ActiveX type library. + /// + /// The imported type whose parent library is to be searched for relevant enumerations. + /// An instance of the representative type. + /// An optional host type collection with which to merge the imported enumerations. + /// A host type collection: if it is not null, a new host type collection otherwise. + public HostTypeCollection typeLibEnums(T obj, HostTypeCollection collection = null) where T : class + { + MiscHelpers.VerifyNonNullArgument(obj, nameof(obj)); + if (collection == null) + { + collection = new HostTypeCollection(); + } + + var type = typeof(T); + if (type.IsUnknownCOMObject()) + { + if (obj is IDispatch dispatch) + { + var typeInfo = dispatch.GetTypeInfo(); + if (typeInfo != null) + { + typeInfo.GetContainingTypeLib().GetReferencedEnums().ForEach(collection.AddEnumTypeInfo); + return collection; + } + } + } + else if (type.IsImport && (type.Assembly.GetOrLoadCustomAttribute(ScriptEngine.Current, false) != null)) + { + type.Assembly.GetReferencedEnums().ForEach(collection.AddType); + return collection; + } + + throw new ArgumentException("The object type is not of an imported (COM/ActiveX) type", nameof(obj)); + } + + // ReSharper restore InconsistentNaming + + #endregion + } +} diff --git a/Unity/Package/Runtime/ExtendedHostFunctions.cs.meta b/Unity/Package/Runtime/ExtendedHostFunctions.cs.meta new file mode 100644 index 000000000..876131b30 --- /dev/null +++ b/Unity/Package/Runtime/ExtendedHostFunctions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4b6409d0b66d8e4989e4d40e4ab62fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ExtensionMethods.cs b/Unity/Package/Runtime/ExtensionMethods.cs new file mode 100644 index 000000000..ca4d5f99d --- /dev/null +++ b/Unity/Package/Runtime/ExtensionMethods.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class ExtensionMethodTable + { + private readonly Dictionary table = new Dictionary(); + + public ExtensionMethodSummary Summary { get; private set; } = new ExtensionMethodSummary(); + + public bool ProcessType(IHostContext context, Type type) + { + Debug.Assert(type.IsSpecific()); + if (!table.ContainsKey(type) && type.HasExtensionMethods(context)) + { + const BindingFlags bindFlags = BindingFlags.Public | BindingFlags.Static; + table[type] = type.GetMethods(bindFlags).Where(method => IsScriptableExtensionMethod(context, method)).ToArray(); + RebuildSummary(context); + return true; + } + + return false; + } + + public void RebuildSummary(IHostContext context) + { + Summary = new ExtensionMethodSummary(context, table); + } + + private static bool IsScriptableExtensionMethod(IHostContext context, MethodInfo method) + { + return method.IsScriptable(context) && method.HasCustomAttributes(context, false); + } + } + + internal sealed class ExtensionMethodSummary + { + public ExtensionMethodSummary() + { + Types = ArrayHelpers.GetEmptyArray(); + Methods = ArrayHelpers.GetEmptyArray(); + MethodNames = ArrayHelpers.GetEmptyArray(); + } + + public ExtensionMethodSummary(IHostContext context, Dictionary table) + { + Types = table.Keys.ToArray(); + Methods = table.SelectMany(pair => pair.Value).ToArray(); + MethodNames = Methods.Select(method => method.GetScriptName(context)).ToArray(); + } + + public Type[] Types { get; } + + public MethodInfo[] Methods { get; } + + public string[] MethodNames { get; } + } +} diff --git a/Unity/Package/Runtime/ExtensionMethods.cs.meta b/Unity/Package/Runtime/ExtensionMethods.cs.meta new file mode 100644 index 000000000..135c7d1f6 --- /dev/null +++ b/Unity/Package/Runtime/ExtensionMethods.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ed99454d755e0b4e97a98b0ad5fb404 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Extensions.cs b/Unity/Package/Runtime/Extensions.cs new file mode 100644 index 000000000..f71fdf013 --- /dev/null +++ b/Unity/Package/Runtime/Extensions.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Defines extension methods for use with all script engines. + /// + public static class Extensions + { + /// + /// Converts a type to a host type for use with script code currently running on the + /// calling thread. + /// + /// The type to convert to a host type. + /// A host type for use with script code. + public static object ToHostType(this Type type) + { + return type.ToHostType(ScriptEngine.Current); + } + + /// + /// Converts a type to a host type for use with script code running in the specified + /// script engine. + /// + /// The type to convert to a host type. + /// The script engine in which the host type will be used. + /// A host type for use with script code. + public static object ToHostType(this Type type, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(type, nameof(type)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + return HostItem.Wrap(engine, HostType.Wrap(type)); + } + + /// + /// Converts an object to a host object with the specified type restriction, for use with + /// script code currently running on the calling thread. + /// + /// The type whose members are to be made accessible from script code. + /// The object to convert to a host object for use with script code. + /// A host object with the specified type restriction. + public static object ToRestrictedHostObject(this T target) + { + return target.ToRestrictedHostObject(ScriptEngine.Current); + } + + /// + /// Converts an object to a host object with the specified type restriction, for use with + /// script code running in the specified script engine. + /// + /// The type whose members are to be made accessible from script code. + /// The object to convert to a host object for use with script code. + /// The script engine in which the host object will be used. + /// A host object with the specified type restriction. + public static object ToRestrictedHostObject(this T target, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + return HostItem.Wrap(engine, target, typeof(T)); + } + + /// + /// Converts an object to a host object with a type restriction specified as a + /// instance, for use with script code currently running on the calling + /// thread. + /// + /// The object to convert to a host object for use with script code. + /// The type whose members are to be made accessible from script code. + /// A host object with the specified type restriction. + public static object ToRestrictedHostObject(this object target, Type type) + { + return target.ToRestrictedHostObject(type, ScriptEngine.Current); + } + + /// + /// Converts an object to a host object with a type restriction specified as a + /// instance, for use with script code running in the specified script + /// engine. + /// + /// The object to convert to a host object for use with script code. + /// The type whose members are to be made accessible from script code. + /// The script engine in which the host object will be used. + /// A host object with the specified type restriction. + public static object ToRestrictedHostObject(this object target, Type type, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + MiscHelpers.VerifyNonNullArgument(type, nameof(type)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + + if (!MiscHelpers.Try(out var holder, () => typeof(Holder<>).MakeGenericType(type).CreateInstance())) + { + throw new ArgumentException("The specified type is invalid", nameof(type)); + } + + if (!MiscHelpers.Try(() => ((IHolder)holder).Value = target)) + { + throw new ArgumentException("The target object is incompatible with the specified type", nameof(target)); + } + + return HostItem.Wrap(engine, target, type); + } + } +} diff --git a/Unity/Package/Runtime/Extensions.cs.meta b/Unity/Package/Runtime/Extensions.cs.meta new file mode 100644 index 000000000..ca44e9cb3 --- /dev/null +++ b/Unity/Package/Runtime/Extensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ddfaa493b4695a143a5792e21eb466d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostEvent.cs b/Unity/Package/Runtime/HostEvent.cs new file mode 100644 index 000000000..e83c2522c --- /dev/null +++ b/Unity/Package/Runtime/HostEvent.cs @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Provides the base implementation for a host event source. + /// + public abstract class EventSource + { + internal EventSource(ScriptEngine engine, object source, EventInfo eventInfo) + { + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + MiscHelpers.VerifyNonNullArgument(eventInfo, nameof(eventInfo)); + + Engine = engine; + Source = source; + EventInfo = eventInfo; + } + + internal ScriptEngine Engine { get; } + + internal abstract Type HandlerType { get; } + + internal object Source { get; } + + internal EventInfo EventInfo { get; } + + #region script-callable interface + + // ReSharper disable InconsistentNaming + + /// + /// Connects the host event source to the specified script handler function. + /// + /// The script function that will handle the event. + /// An that represents the connection. + public EventConnection connect(object scriptFunc) + { + MiscHelpers.VerifyNonNullArgument(scriptFunc, nameof(scriptFunc)); + return Engine.CreateEventConnection(HandlerType, Source, EventInfo, DelegateFactory.CreateDelegate(Engine, scriptFunc, HandlerType)); + } + + // ReSharper restore InconsistentNaming + + #endregion + } + + /// + /// Represents a host event source. + /// + /// The event handler delegate type. + public sealed class EventSource : EventSource + { + internal EventSource(ScriptEngine engine, object source, EventInfo eventInfo) + : base(engine, source, eventInfo) + { + if (eventInfo.EventHandlerType != typeof(T)) + { + throw new ArgumentException("Invalid event type (handler type mismatch)", nameof(eventInfo)); + } + } + + #region EventSource overrides + + internal override Type HandlerType => typeof(T); + + #endregion + + #region script-callable interface + + // ReSharper disable InconsistentNaming + + /// + /// Connects the host event source to the specified script handler function. + /// + /// The script function that will handle the event. + /// An that represents the connection. + public new EventConnection connect(object scriptFunc) + { + MiscHelpers.VerifyNonNullArgument(scriptFunc, nameof(scriptFunc)); + return Engine.CreateEventConnection(Source, EventInfo, DelegateFactory.CreateDelegate(Engine, scriptFunc, typeof(T))); + } + + // ReSharper restore InconsistentNaming + + #endregion + } + + /// + /// Provides the base implementation for a connection between a host event source and a script handler function. + /// + public abstract class EventConnection + { + private readonly ScriptEngine engine; + private readonly object source; + private readonly MethodInfo removeMethod; + private readonly object[] parameters; + private readonly InterlockedOneWayFlag brokenFlag = new InterlockedOneWayFlag(); + + internal EventConnection(ScriptEngine engine, object source, EventInfo eventInfo, Delegate handler) + { + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + MiscHelpers.VerifyNonNullArgument(handler, nameof(handler)); + MiscHelpers.VerifyNonNullArgument(eventInfo, nameof(eventInfo)); + + if (!MiscHelpers.Try(out var addMethod, () => eventInfo.GetAddMethod(true)) || (addMethod == null)) + { + throw new ArgumentException("Invalid event type (no accessible add method)", nameof(eventInfo)); + } + + if (!MiscHelpers.Try(out removeMethod, () => eventInfo.GetRemoveMethod(true)) || (removeMethod == null)) + { + throw new ArgumentException("Invalid event type (no accessible remove method)", nameof(eventInfo)); + } + + this.engine = engine; + this.source = source; + + addMethod.Invoke(source, parameters = new object[] { handler }); + } + + internal void Break() + { + if (brokenFlag.Set()) + { + removeMethod.Invoke(source, parameters); + } + } + + #region script-callable interface + + // ReSharper disable InconsistentNaming + + /// + /// Disconnects the host event source from the script handler function. + /// + public void disconnect() + { + engine.BreakEventConnection(this); + } + + // ReSharper restore InconsistentNaming + + #endregion + } + + /// + /// Represents a connection between a host event source and a script handler function. + /// + /// The event handler delegate type. + public sealed class EventConnection : EventConnection + { + internal EventConnection(ScriptEngine engine, object source, EventInfo eventInfo, Delegate handler) + : base(engine, source, eventInfo, handler) + { + if (eventInfo.EventHandlerType != typeof(T)) + { + throw new ArgumentException("Invalid event type (handler type mismatch)", nameof(eventInfo)); + } + } + } +} diff --git a/Unity/Package/Runtime/HostEvent.cs.meta b/Unity/Package/Runtime/HostEvent.cs.meta new file mode 100644 index 000000000..8eeb23422 --- /dev/null +++ b/Unity/Package/Runtime/HostEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 339174710f7cf6f479fc36af70f62be1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostFunctions.cs b/Unity/Package/Runtime/HostFunctions.cs new file mode 100644 index 000000000..94a5230eb --- /dev/null +++ b/Unity/Package/Runtime/HostFunctions.cs @@ -0,0 +1,1373 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Provides optional script-callable utility functions. + /// + /// + /// Use AddHostObject to expose a + /// HostFunctions instance to script code. Each instance can only be exposed in one + /// script engine. + /// + public class HostFunctions : IScriptableObject + { + private ScriptEngine engine; + + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public HostFunctions() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + #region script-callable interface + + // ReSharper disable InconsistentNaming + + /// + /// Creates an empty host object. + /// + /// A new empty host object. + /// + /// This function is provided for script languages that do not support external + /// instantiation. It creates an object that supports dynamic property addition and + /// removal. The host can manipulate it via the interface. + /// + /// + /// The following code creates an empty host object and adds several properties to it. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var item = host.newObj(); + /// item.label = "Widget"; + /// item.weight = 123.45; + /// + /// + public PropertyBag newObj() + { + return new PropertyBag(); + } + + /// + /// Creates a host object of the specified type. This version is invoked if the specified + /// type can be used as a type argument. + /// + /// The type of object to create. + /// Optional constructor arguments. + /// A new host object of the specified type. + /// + /// + /// This function is provided for script languages that do not support external + /// instantiation. It is overloaded with and + /// selected at runtime if can be used as a type argument. + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see + /// AddHostObject. + /// + /// + /// + /// The following code imports the class, creates an + /// instance using the + /// Random(Int32) + /// constructor, and calls the method. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var RandomT = host.type("System.Random"); + /// var random = host.newObj(RandomT, 100); + /// var value = random.NextDouble(); + /// + /// + /// + public T newObj(params object[] args) + { + return (T)typeof(T).CreateInstance(args); + } + + /// + /// Creates a host object of the specified type. This version is invoked if the specified + /// type cannot be used as a type argument. + /// + /// The type of object to create. + /// Optional constructor arguments. + /// A new host object of the specified type. + /// + /// + /// This function is provided for script languages that do not support external + /// instantiation. It is overloaded with and selected at runtime if + /// cannot be used as a type argument. Note that this applies + /// to some host types that support instantiation, such as certain COM/ActiveX types. + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see + /// AddHostObject. + /// + /// + public object newObj(object type, params object[] args) + { + return GetUniqueHostType(type, "type").CreateInstance(args); + } + + /// + /// Performs dynamic instantiation. + /// + /// The dynamic host object that provides the instantiation operation to perform. + /// Optional instantiation arguments. + /// The result of the operation, which is usually a new dynamic host object. + /// + /// This function is provided for script languages that do not support external + /// instantiation. + /// + public object newObj(IDynamicMetaObjectProvider target, params object[] args) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TryCreateInstance(args, out var result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic instantiation"); + } + + /// + /// Creates a host array with the specified element type. + /// + /// The element type of the array to create. + /// One or more integers representing the array dimension lengths. + /// A new host array with the specified element type. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see + /// AddHostObject. + /// + /// + /// The following code creates a 5x3 host array of strings. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var StringT = host.type("System.String"); + /// var array = host.newArr(StringT, 5, 3); + /// + /// + /// + /// + public object newArr(params int[] lengths) + { + return Array.CreateInstance(typeof(T), lengths); + } + + /// + /// Creates a host array with as the element type. + /// + /// One or more integers representing the array dimension lengths. + /// A new host array with as the element type. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see + /// AddHostObject. + /// + /// + public object newArr(params int[] lengths) + { + return newArr(lengths); + } + + /// + /// Creates a host variable of the specified type. + /// + /// The type of variable to create. + /// An optional initial value for the variable. + /// A new host variable of the specified type. + /// + /// + /// A host variable is a strongly typed object that holds a value of the specified type. + /// Host variables are useful for passing method arguments by reference. In addition to + /// being generally interchangeable with their stored values, host variables support the + /// following properties: + /// + /// + /// + /// + /// Property + /// Access + /// Description + /// + /// + /// value + /// read-write + /// The current value of the host variable. + /// + /// + /// out + /// read-only + /// A reference to the host variable that can be passed as an out argument. + /// + /// + /// ref + /// read-only + /// A reference to the host variable that can be passed as a ref argument. + /// + /// + /// + /// + /// + /// The following code demonstrates using a host variable to invoke a method with an + /// out parameter. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import a dictionary type + /// var StringT = host.type("System.String"); + /// var StringDictT = host.type("System.Collections.Generic.Dictionary", StringT, StringT); + /// // create and populate a dictionary + /// var dict = host.newObj(StringDictT); + /// dict.Add("foo", "bar"); + /// dict.Add("baz", "qux"); + /// // look up a dictionary entry + /// var result = host.newVar(StringT); + /// var found = dict.TryGetValue("baz", result.out); + /// + /// + /// + public object newVar(T initValue = default) + { + return new HostVariable(initValue); + } + + /// + /// Creates a delegate that invokes a script function. + /// + /// The type of delegate to create. + /// The script function for which to create a delegate. + /// A new delegate that invokes the specified script function. + /// + /// If the delegate signature includes parameters passed by reference, the corresponding + /// arguments to the script function will be host variables. + /// The script function can set the value of an output argument by assigning the + /// corresponding host variable's value property. + /// + /// + /// The following code demonstrates delegating a callback to a script function. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // create and populate an array of integers + /// var EnumerableT = host.type("System.Linq.Enumerable", "System.Core"); + /// var array = EnumerableT.Range(1, 5).ToArray(); + /// // import the callback type required to call Array.ForEach + /// var Int32T = host.type("System.Int32"); + /// var CallbackT = host.type("System.Action", Int32T); + /// // use Array.ForEach to calculate a sum + /// var sum = 0; + /// var ArrayT = host.type("System.Array"); + /// ArrayT.ForEach(array, host.del(CallbackT, function (value) { sum += value; })); + /// + /// + /// + /// + public T del(object scriptFunc) + { + return DelegateFactory.CreateDelegate(GetEngine(), scriptFunc); + } + + /// + /// Creates a delegate that invokes a script function and returns no value. + /// + /// The number of arguments to pass to the script function. + /// The script function for which to create a delegate. + /// A new delegate that invokes the specified script function and returns no value. + /// + /// This function creates a delegate that accepts arguments and + /// returns no value. The type of all parameters is . Such a + /// delegate is often useful in strongly typed contexts because of + /// contravariance. + /// + /// + /// The following code demonstrates delegating a callback to a script function. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // create and populate an array of strings + /// var StringT = host.type("System.String"); + /// var array = host.newArr(StringT, 3); + /// array.SetValue("first", 0); + /// array.SetValue("second", 1); + /// array.SetValue("third", 2); + /// // use Array.ForEach to generate console output + /// var ArrayT = host.type("System.Array"); + /// var ConsoleT = host.type("System.Console"); + /// ArrayT.ForEach(array, host.proc(1, function (value) { ConsoleT.WriteLine(value); })); + /// + /// + /// + /// + public object proc(int argCount, object scriptFunc) + { + return DelegateFactory.CreateProc(GetEngine(), scriptFunc, argCount); + } + + /// + /// Creates a delegate that invokes a script function and returns a value of the specified type. + /// + /// The return value type. + /// The number of arguments to pass to the script function. + /// The script function for which to create a delegate. + /// A new delegate that invokes the specified script function and returns a value of the specified type. + /// + /// This function creates a delegate that accepts arguments and + /// returns a value of the specified type. The type of all parameters is + /// . Such a delegate is often useful in strongly typed contexts + /// because of + /// contravariance. + /// + /// + /// The following code demonstrates delegating a callback to a script function. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // create and populate an array of strings + /// var StringT = host.type("System.String"); + /// var array = host.newArr(StringT, 3); + /// array.SetValue("first", 0); + /// array.SetValue("second", 1); + /// array.SetValue("third", 2); + /// // import LINQ extensions + /// var EnumerableT = host.type("System.Linq.Enumerable", "System.Core"); + /// // use LINQ to create an array of modified strings + /// var selector = host.func(StringT, 1, function (value) { return value.toUpperCase(); }); + /// array = array.Select(selector).ToArray(); + /// + /// + /// + /// + /// + public object func(int argCount, object scriptFunc) + { + return DelegateFactory.CreateFunc(GetEngine(), scriptFunc, argCount); + } + + /// + /// Creates a delegate that invokes a script function and returns its result value. + /// + /// The number of arguments to pass to the script function. + /// The script function for which to create a delegate. + /// A new delegate that invokes the specified script function and returns its result value. + /// + /// + /// This function creates a delegate that accepts arguments and + /// returns the result of invoking . The type of all + /// parameters and the return value is . Such a delegate is + /// often useful in strongly typed contexts because of + /// contravariance. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + /// + public object func(int argCount, object scriptFunc) + { + return func(argCount, scriptFunc); + } + + /// + /// Gets the for the specified host type. This version is invoked + /// if the specified object can be used as a type argument. + /// + /// The host type for which to get the . + /// The for the specified host type. + /// + /// + /// This function is similar to C#'s + /// typeof + /// operator. It is overloaded with and selected at runtime if + /// can be used as a type argument. + /// + /// + /// This function throws an exception if the script engine's + /// property is set to false. + /// + /// + /// + /// The following code retrieves the assembly-qualified name of a host type. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var StringT = host.type("System.String"); + /// var name = host.typeOf(StringT).AssemblyQualifiedName; + /// + /// + /// + public Type typeOf() + { + GetEngine().CheckReflection(); + return typeof(T); + } + + /// + /// Gets the for the specified host type. This version is invoked + /// if the specified object cannot be used as a type argument. + /// + /// The host type for which to get the . + /// The for the specified host type. + /// + /// + /// This function is similar to C#'s + /// typeof + /// operator. It is overloaded with and selected at runtime if + /// cannot be used as a type argument. Note that this applies to + /// some host types; examples are static types and overloaded generic type groups. + /// + /// + /// This function throws an exception if the script engine's + /// property is set to false. + /// + /// + /// + /// The following code retrieves the assembly-qualified name of a host type. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var ConsoleT = host.type("System.Console"); + /// var name = host.typeOf(ConsoleT).AssemblyQualifiedName; + /// + /// + /// + public Type typeOf(object value) + { + GetEngine().CheckReflection(); + return GetUniqueHostType(value, "value"); + } + + /// + /// Determines whether an object is compatible with the specified host type. + /// + /// The host type with which to test for compatibility. + /// The object to test for compatibility with the specified host type. + /// True if is compatible with the specified type, false otherwise. + /// + /// This function is similar to C#'s + /// is + /// operator. + /// + /// + /// The following code defines a function that determines whether an object implements + /// . + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// function isComparable(value) + /// { + /// var IComparableT = host.type("System.IComparable"); + /// return host.isType(IComparableT, value); + /// } + /// + /// + /// + public bool isType(object value) + { + return value is T; + } + + /// + /// Casts an object to the specified host type, returning null if the cast fails. + /// + /// The host type to which to cast . + /// The object to cast to the specified host type. + /// The result of the cast if successful, null otherwise. + /// + /// This function is similar to C#'s + /// as + /// operator. + /// + /// + /// The following code defines a function that disposes an object if it implements + /// . + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// function dispose(value) + /// { + /// var IDisposableT = host.type("System.IDisposable"); + /// var disposable = host.asType(IDisposableT, value); + /// if (disposable) { + /// disposable.Dispose(); + /// } + /// } + /// + /// + /// + public object asType(object value) where T : class + { + return HostItem.Wrap(GetEngine(), value as T, typeof(T)); + } + + /// + /// Casts an object to the specified host type. + /// + /// The host type to which to cast . + /// The object to cast to the specified host type. + /// The result of the cast. + /// + /// If the cast fails, this function throws an exception. + /// + /// + /// The following code casts a floating-point value to a 32-bit integer. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// var Int32T = host.type("System.Int32"); + /// var intValue = host.cast(Int32T, 12.5); + /// + /// + /// + public object cast(object value) + { + return HostItem.Wrap(GetEngine(), value.DynamicCast(), typeof(T)); + } + + /// + /// Determines whether an object is a host type. This version is invoked if the specified + /// object cannot be used as a type argument. + /// + /// The object to test. + /// True if is a host type, false otherwise. + /// + /// This function is overloaded with and selected at runtime if + /// cannot be used as a type argument. Note that this applies to + /// some host types; examples are static types and overloaded generic type groups. + /// + public bool isTypeObj(object value) + { + return value is HostType; + } + + // ReSharper disable UnusedTypeParameter + + /// + /// Determines whether an object is a host type. This version is invoked if the specified + /// object can be used as a type argument. + /// + /// The host type (ignored). + /// True. + /// + /// This function is overloaded with and selected at + /// runtime if can be used as a type argument. Because type + /// arguments are always host types, this method ignores its type argument and always + /// returns true. + /// + public bool isTypeObj() + { + return true; + } + + // ReSharper restore UnusedTypeParameter + + /// + /// Determines whether the specified value is null. + /// + /// The value to test. + /// True if is null, false otherwise. + /// + /// Use this function to test field, property, and method return values when null + /// result wrapping is in effect (see + /// and + /// ). + /// + /// + /// + public bool isNull(object value) + { + return value == null; + } + + /// + /// Creates a strongly typed flag set. + /// + /// The type of flag set to create. + /// The flags to include in the flag set. + /// A strongly typed flag set containing the specified flags. + /// + /// This function throws an exception if is not a flag set type. + /// + /// + /// The following code demonstrates using a strongly typed flag set. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import URI types + /// var UriT = host.type("System.Uri", "System"); + /// var UriFormatT = host.type("System.UriFormat", "System"); + /// var UriComponentsT = host.type("System.UriComponents", "System"); + /// // create a URI + /// var uri = host.newObj(UriT, "http://www.example.com:8080/path/to/file/sample.htm?x=1&y=2"); + /// // extract URI components + /// var components = host.flags(UriComponentsT.Scheme, UriComponentsT.Host, UriComponentsT.Path); + /// var result = uri.GetComponents(components, UriFormatT.Unescaped); + /// + /// + /// + public T flags(params T[] args) + { + var type = typeof(T); + if (!type.IsFlagsEnum(ScriptEngine.Current)) + { + throw new InvalidOperationException(MiscHelpers.FormatInvariant("{0} is not a flag set type", type.GetFullFriendlyName())); + } + + try + { + return (T)Enum.ToObject(typeof(T), args.Aggregate(0UL, (flags, arg) => flags | Convert.ToUInt64(arg, CultureInfo.InvariantCulture))); + } + catch (OverflowException) + { + return (T)Enum.ToObject(typeof(T), args.Aggregate(0L, (flags, arg) => flags | Convert.ToInt64(arg, CultureInfo.InvariantCulture))); + } + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.SByte"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toSByte(42)); + /// + /// + /// + public object toSByte(IConvertible value) + { + return HostObject.Wrap(Convert.ToSByte(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Byte"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toByte(42)); + /// + /// + /// + public object toByte(IConvertible value) + { + return HostObject.Wrap(Convert.ToByte(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Int16"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toInt16(42)); + /// + /// + /// + public object toInt16(IConvertible value) + { + return HostObject.Wrap(Convert.ToInt16(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.UInt16"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toUInt16(42)); + /// + /// + /// + public object toUInt16(IConvertible value) + { + return HostObject.Wrap(Convert.ToUInt16(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Char"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toChar(42)); + /// + /// + /// + public object toChar(IConvertible value) + { + return HostObject.Wrap(Convert.ToChar(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Int32"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toInt32(42)); + /// + /// + /// + public object toInt32(IConvertible value) + { + return HostObject.Wrap(Convert.ToInt32(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.UInt32"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toUInt32(42)); + /// + /// + /// + public object toUInt32(IConvertible value) + { + return HostObject.Wrap(Convert.ToUInt32(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Int64"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toInt64(42)); + /// + /// + /// + public object toInt64(IConvertible value) + { + return HostObject.Wrap(Convert.ToInt64(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.UInt64"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toUInt64(42)); + /// + /// + /// + public object toUInt64(IConvertible value) + { + return HostObject.Wrap(Convert.ToUInt64(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Single"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toSingle(42)); + /// + /// + /// + public object toSingle(IConvertible value) + { + return HostObject.Wrap(Convert.ToSingle(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Double"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toDouble(42)); + /// + /// + /// + public object toDouble(IConvertible value) + { + return HostObject.Wrap(Convert.ToDouble(value)); + } + + /// + /// Converts the specified value to a strongly typed instance. + /// + /// The value to convert. + /// An object that can be passed to a parameter of type . + /// + /// This function converts to and + /// packages the result to retain its numeric type across the host-script boundary. It may + /// be useful for passing arguments to parameters if the script + /// engine does not support that type natively. + /// + /// + /// The following code adds an element of type to a strongly + /// typed list. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ElementT = host.type("System.Decimal"); + /// var ListT = host.type("System.Collections.Generic.List", ElementT); + /// // create a list + /// var list = host.newObj(ListT); + /// // add a list element + /// list.Add(host.toDecimal(42)); + /// + /// + /// + public object toDecimal(IConvertible value) + { + return HostObject.Wrap(Convert.ToDecimal(value)); + } + + /// + /// Gets the value of a property in a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to get. + /// The name of the property to get. + /// The value of the specified property. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public object getProperty(IPropertyBag target, string name) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.TryGetValue(name, out var result)) + { + return result; + } + + return Nonexistent.Value; + } + + /// + /// Sets a property value in a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to set. + /// The name of the property to set. + /// The new value of the specified property. + /// The result of the operation, which is usually the value assigned to the specified property. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public object setProperty(IPropertyBag target, string name, object value) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + return target[name] = value; + } + + /// + /// Removes a property from a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to remove. + /// The name of the property to remove. + /// True if the property was found and removed, false otherwise. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public bool removeProperty(IPropertyBag target, string name) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + return target.Remove(name); + } + + /// + /// Gets the value of a property in a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to get. + /// The name of the property to get. + /// The value of the specified property. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public object getProperty(IDynamicMetaObjectProvider target, string name) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TryGetMember(name, out var result)) + { + return result; + } + + return Nonexistent.Value; + } + + /// + /// Sets a property value in a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to set. + /// The name of the property to set. + /// The new value of the specified property. + /// The result of the operation, which is usually the value assigned to the specified property. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public object setProperty(IDynamicMetaObjectProvider target, string name, object value) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TrySetMember(name, value, out var result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic property assignment"); + } + + /// + /// Removes a property from a dynamic host object that implements . + /// + /// The dynamic host object that contains the property to remove. + /// The name of the property to remove. + /// True if the property was found and removed, false otherwise. + /// + /// This function is provided for script languages that do not support dynamic properties. + /// + public bool removeProperty(IDynamicMetaObjectProvider target, string name) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TryDeleteMember(name, out var result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic property deletion"); + } + + /// + /// Gets the value of an element in a dynamic host object that implements . + /// + /// The dynamic host object that contains the element to get. + /// One or more indices that identify the element to get. + /// The value of the specified element. + /// + /// This function is provided for script languages that do not support general indexing. + /// + public object getElement(IDynamicMetaObjectProvider target, params object[] indices) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TryGetIndex(indices, out var result)) + { + return result; + } + + return Nonexistent.Value; + + } + + /// + /// Sets an element value in a dynamic host object that implements . + /// + /// The dynamic host object that contains the element to set. + /// The new value of the element. + /// One or more indices that identify the element to set. + /// The result of the operation, which is usually the value assigned to the specified element. + /// + /// This function is provided for script languages that do not support general indexing. + /// + public object setElement(IDynamicMetaObjectProvider target, object value, params object[] indices) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TrySetIndex(indices, value, out var result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic element assignment"); + } + + /// + /// Removes an element from a dynamic host object that implements . + /// + /// The dynamic host object that contains the element to remove. + /// One or more indices that identify the element to remove. + /// True if the element was found and removed, false otherwise. + /// + /// This function is provided for script languages that do not support general indexing. + /// + public bool removeElement(IDynamicMetaObjectProvider target, params object[] indices) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + + if (target.GetMetaObject(Expression.Constant(target)).TryDeleteIndex(indices, out var result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic element deletion"); + } + + /// + /// Casts a dynamic host object to its static type. + /// + /// The object to cast to its static type. + /// The specified object in its static type form, stripped of its dynamic members. + /// + /// A dynamic host object that implements may have + /// dynamic members that override members of its static type. This function can be used to + /// gain access to type members overridden in this manner. + /// + public object toStaticType(IDynamicMetaObjectProvider value) + { + return HostItem.Wrap(GetEngine(), value, HostItemFlags.HideDynamicMembers); + } + + /// + /// Allows script code to handle host exceptions. + /// + /// A script function that invokes one or more host methods or properties. + /// A script function to invoke if throws an exception. + /// An optional script function that performs cleanup for the operation. + /// True if completed successfully, false if it threw an exception that was handled by . + /// + /// This function uses a try-catch-finally statement to invoke + /// . If an exception is thrown, it is caught and passed to + /// for analysis. If returns + /// false, the exception is rethrown. Regardless of the outcome, + /// , if specified, is invoked as a final step before the + /// function exits. + /// + /// + /// The following code demonstrates handling host exceptions in script code. + /// It assumes that an instance of is exposed under + /// the name "host" + /// (see AddHostObject). + /// + /// // import types + /// var ConsoleT = host.type("System.Console"); + /// var WebClientT = host.type("System.Net.WebClient", "System"); + /// // create a Web client + /// var webClient = host.newObj(WebClientT); + /// host.tryCatch( + /// function () { + /// // download Web document + /// ConsoleT.WriteLine(webClient.DownloadString("http://cnn.com")); + /// }, + /// function (exception) { + /// // dump exception + /// ConsoleT.WriteLine("*** ERROR: " + exception.GetBaseException().ToString()); + /// return true; + /// }, + /// function () { + /// // clean up + /// ConsoleT.WriteLine("*** CLEANING UP ***"); + /// webClient.Dispose(); + /// } + /// ); + /// + /// + /// + /// + public bool tryCatch(object tryFunc, object catchFunc, object finallyFunc = null) + { + MiscHelpers.VerifyNonNullArgument(tryFunc, nameof(tryFunc)); + MiscHelpers.VerifyNonNullArgument(catchFunc, nameof(catchFunc)); + + try + { + ((ScriptObject)tryFunc).InvokeAsFunction(); + return true; + } + catch (Exception exception) + { + if (!Convert.ToBoolean(((ScriptObject)catchFunc).InvokeAsFunction(exception))) + { + throw; + } + + return false; + } + finally + { + if (finallyFunc != null) + { + ((ScriptObject)finallyFunc).InvokeAsFunction(); + } + } + } + + // ReSharper restore InconsistentNaming + + #endregion + + internal ScriptEngine GetEngine() + { + var activeEngine = ScriptEngine.Current ?? engine; + if (activeEngine == null) + { + throw new InvalidOperationException("Operation requires a script engine"); + } + + return activeEngine; + } + + internal static Type GetUniqueHostType(object type, string paramName) + { + var hostType = type as HostType; + if (hostType == null) + { + throw new ArgumentException("Invalid host type", paramName); + } + + if (hostType.Types.Length > 1) + { + throw new ArgumentException(MiscHelpers.FormatInvariant("'{0}' does not identify a unique host type", hostType.Types[0].GetLocator()), paramName); + } + + return hostType.Types[0]; + } + + #region IScriptableObject implementation + + // ReSharper disable ParameterHidesMember + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + void IScriptableObject.OnExposedToScriptCode(ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + this.engine = engine; + } + + // ReSharper restore ParameterHidesMember + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostFunctions.cs.meta b/Unity/Package/Runtime/HostFunctions.cs.meta new file mode 100644 index 000000000..ce784cf35 --- /dev/null +++ b/Unity/Package/Runtime/HostFunctions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c62ebd9afb5aa404db6b35f7aa9129c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostIndexedProperty.cs b/Unity/Package/Runtime/HostIndexedProperty.cs new file mode 100644 index 000000000..79a0c2867 --- /dev/null +++ b/Unity/Package/Runtime/HostIndexedProperty.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class HostIndexedProperty : HostTarget + { + private static readonly string[] auxMethodNames = { "get", "set" }; + + private readonly HostItem target; + private readonly string name; + + public HostIndexedProperty(HostItem target, string name) + { + this.target = target; + this.name = name; + } + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("HostIndexedProperty:{0}", name); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => typeof(void); + + public override object Target => this; + + public override object InvokeTarget => null; + + public override object DynamicInvokeTarget => null; + + public override HostTargetFlags GetFlags(IHostContext context) + { + return HostTargetFlags.None; + } + + public override string[] GetAuxMethodNames(IHostContext context, BindingFlags bindFlags) + { + return auxMethodNames; + } + + public override bool TryInvokeAuxMember(IHostContext context, string memberName, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + { + if (string.Equals(memberName, "get", invokeFlags.GetMemberNameComparison())) + { + result = target.InvokeMember(name, BindingFlags.GetProperty | BindingFlags.SuppressChangeType, args, bindArgs, null, true); + return true; + } + + if (string.Equals(memberName, "set", invokeFlags.GetMemberNameComparison())) + { + result = target.InvokeMember(name, BindingFlags.SetProperty | BindingFlags.SuppressChangeType, args, bindArgs, null, true); + return true; + } + } + + result = null; + return false; + } + + public override bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + result = target.InvokeMember(name, (invokeFlags.HasFlag(BindingFlags.SetField) ? BindingFlags.SetProperty : BindingFlags.GetProperty) | BindingFlags.SuppressChangeType, args, bindArgs, null, true); + return true; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return Invocability.Delegate; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostIndexedProperty.cs.meta b/Unity/Package/Runtime/HostIndexedProperty.cs.meta new file mode 100644 index 000000000..e0050bbd0 --- /dev/null +++ b/Unity/Package/Runtime/HostIndexedProperty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 279bef5cb677e4c4cb8721abed2dba90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostItem.InvokeMethod.cs b/Unity/Package/Runtime/HostItem.InvokeMethod.cs new file mode 100644 index 000000000..56d8c8b9c --- /dev/null +++ b/Unity/Package/Runtime/HostItem.InvokeMethod.cs @@ -0,0 +1,609 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Threading; +using Microsoft.CSharp.RuntimeBinder; +using Microsoft.ClearScript.Util; +using Binder = Microsoft.CSharp.RuntimeBinder.Binder; + +namespace Microsoft.ClearScript +{ + internal partial class HostItem + { + #region data + + private static readonly ConcurrentDictionary coreBindCache = new ConcurrentDictionary(); + private static long coreBindCount; + + #endregion + + #region internal members + + private object InvokeMethod(string name, object[] args, object[] bindArgs) + { + var typeArgs = GetTypeArgs(args).ToArray(); + if (typeArgs.Length > 0) + { + var mergedArgs = args; + var argOffset = typeArgs.Length; + + args = args.Skip(argOffset).ToArray(); + bindArgs = bindArgs.Skip(argOffset).ToArray(); + + var result = InvokeMethod(name, typeArgs, args, bindArgs); + for (var index = 0; index < args.Length; index++) + { + mergedArgs[argOffset + index] = args[index]; + } + + return result; + } + + return InvokeMethod(name, typeArgs, args, bindArgs); + } + + private object InvokeMethod(string name, Type[] typeArgs, object[] args, object[] bindArgs) + { + var bindResult = BindMethod(name, typeArgs, args, bindArgs); + if (!bindResult.IsSuccess && Target.GetFlags(this).HasFlag(HostTargetFlags.AllowExtensionMethods)) + { + var targetArg = Target.Target.ToEnumerable(); + var extensionArgs = targetArg.Concat(args).ToArray(); + + var targetBindArg = new object[] { Target }; + var extensionBindArgs = targetBindArg.Concat(bindArgs).ToArray(); + + foreach (var type in ExtensionMethodSummary.Types) + { + var extensionHostItem = (HostItem)Wrap(Engine, HostType.Wrap(type)); + var extensionBindResult = extensionHostItem.BindMethod(name, typeArgs, extensionArgs, extensionBindArgs); + if (extensionBindResult.IsSuccess) + { + var result = extensionBindResult.Invoke(extensionHostItem); + for (var index = 1; index < extensionArgs.Length; index++) + { + args[index - 1] = extensionArgs[index]; + } + + return result; + } + } + } + + return bindResult.Invoke(this); + } + + private static IEnumerable GetTypeArgs(object[] args) + { + foreach (var arg in args) + { + var hostType = arg as HostType; + if (hostType == null) + { + yield break; + } + + var typeArg = hostType.GetTypeArgNoThrow(); + if (typeArg == null) + { + yield break; + } + + yield return typeArg; + } + } + + private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args, object[] bindArgs) + { + var bindFlags = GetMethodBindFlags(); + + // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification + // will result in bugs that are difficult to diagnose. Create a copy if necessary. + + var signature = new BindSignature(AccessContext, bindFlags, Target, name, typeArgs, bindArgs); + MethodBindResult result; + + if (Engine.TryGetCachedMethodBindResult(signature, out var rawResult)) + { + result = MethodBindResult.Create(name, bindFlags, rawResult, Target, args); + } + else + { + var forceReflection = Engine.DisableDynamicBinding; + + if (forceReflection) + { + result = new MethodBindResult(() => new MissingMethodException(MiscHelpers.FormatInvariant("The object has no method named '{0}' that matches the specified arguments", name))); + } + else + { + result = BindMethodInternal(signature, AccessContext, bindFlags, Target, name, typeArgs, args, bindArgs); + if (!result.IsPreferredMethod(this, name)) + { + if (result.IsSuccess) + { + result = new MethodBindResult(() => new MissingMethodException(MiscHelpers.FormatInvariant("The object has no method named '{0}' that matches the specified arguments", name))); + } + + foreach (var altName in GetAltMethodNames(name, bindFlags)) + { + var altResult = BindMethodInternal(null, AccessContext, bindFlags, Target, altName, typeArgs, args, bindArgs); + if (altResult.IsUnblockedMethod(this)) + { + result = altResult; + break; + } + } + } + } + + if ((!result.IsSuccess) && (forceReflection || Engine.UseReflectionBindFallback)) + { + var reflectionResult = BindMethodUsingReflection(bindFlags, Target, name, typeArgs, args, bindArgs); + if ((reflectionResult.IsSuccess) || forceReflection) + { + result = reflectionResult; + } + } + + Engine.CacheMethodBindResult(signature, result.RawResult); + } + + return result; + } + + private static MethodBindResult BindMethodInternal(BindSignature signature, Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs) + { + if (signature == null) + { + // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification + // will result in bugs that are difficult to diagnose. Create a copy if necessary. + + signature = new BindSignature(bindContext, bindFlags, target, name, typeArgs, bindArgs); + } + + MethodBindResult result; + + if (coreBindCache.TryGetValue(signature, out var rawResult)) + { + result = MethodBindResult.Create(name, bindFlags, rawResult, target, args); + } + else + { + result = BindMethodCore(bindContext, bindFlags, target, name, typeArgs, args, bindArgs); + coreBindCache.TryAdd(signature, result.RawResult); + } + + return result; + } + + private static MethodBindResult BindMethodCore(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs) + { + Interlocked.Increment(ref coreBindCount); + + // create C# member invocation binder + const CSharpBinderFlags binderFlags = CSharpBinderFlags.InvokeSimpleName | CSharpBinderFlags.ResultDiscarded; + var binder = (InvokeMemberBinder)Binder.InvokeMember(binderFlags, name, typeArgs, bindContext, CreateArgInfoEnum(target, bindArgs)); + + // perform default binding + var rawResult = BindMethodRaw(bindFlags, binder, target, bindArgs); + + var result = MethodBindResult.Create(name, bindFlags, rawResult, target, args); + if (!result.IsSuccess && !(target is HostType) && target.Type.IsInterface) + { + // binding through interface failed; try base interfaces + foreach (var interfaceType in target.Type.GetInterfaces()) + { + var baseInterfaceTarget = HostObject.Wrap(target.InvokeTarget, interfaceType); + rawResult = BindMethodRaw(bindFlags, binder, baseInterfaceTarget, bindArgs); + + var baseInterfaceResult = MethodBindResult.Create(name, bindFlags, rawResult, target, args); + if (baseInterfaceResult.IsSuccess) + { + return baseInterfaceResult; + } + } + + // binding through base interfaces failed; try System.Object + var objectTarget = HostObject.Wrap(target.InvokeTarget, typeof(object)); + rawResult = BindMethodRaw(bindFlags, binder, objectTarget, bindArgs); + + var objectResult = MethodBindResult.Create(name, bindFlags, rawResult, target, args); + if (objectResult.IsSuccess) + { + return objectResult; + } + } + + return result; + } + + private static object BindMethodRaw(BindingFlags bindFlags, InvokeMemberBinder binder, HostTarget target, object[] bindArgs) + { + var expr = DynamicHelpers.Bind(binder, target, bindArgs).Expression; + + // ReSharper disable ConditionIsAlwaysTrueOrFalse + // ReSharper disable HeuristicUnreachableCode + + if (expr == null) + { + return new Func(() => new MissingMethodException(MiscHelpers.FormatInvariant("The object has no method named '{0}'", binder.Name))); + } + + // ReSharper restore HeuristicUnreachableCode + // ReSharper restore ConditionIsAlwaysTrueOrFalse + + if (expr.NodeType == ExpressionType.Dynamic) + { + // The binding result is a dynamic call, which is indicative of COM interop. This + // sort of binding is not very useful here; it can't be resolved to a MethodInfo + // instance, and caching it is problematic because it includes argument bindings. + // Falling back to reflection should work in most cases because COM interfaces + // support neither generic nor overloaded methods. + + try + { + var method = target.Type.GetMethod(binder.Name, bindFlags); + return (object)method ?? new Func(() => new MissingMethodException(MiscHelpers.FormatInvariant("The object has no method named '{0}'", binder.Name))); + } + catch (AmbiguousMatchException exception) + { + return new Func(() => new AmbiguousMatchException(exception.Message)); + } + } + + return (new MethodBindingVisitor(target.InvokeTarget, binder.Name, expr)).Result; + } + + private IEnumerable GetAltMethodNames(string name, BindingFlags bindFlags) + { + return GetAltMethodNamesInternal(name, bindFlags).Distinct(); + } + + private IEnumerable GetAltMethodNamesInternal(string name, BindingFlags bindFlags) + { + foreach (var method in Target.Type.GetScriptableMethods(this, name, bindFlags)) + { + var methodName = method.GetShortName(); + if (methodName != name) + { + yield return methodName; + } + } + } + + private static IEnumerable CreateArgInfoEnum(HostTarget target, object[] args) + { + if (target is HostType) + { + yield return CreateStaticTypeArgInfo(); + } + else + { + yield return CreateArgInfo(target.DynamicInvokeTarget); + } + + foreach (var arg in args) + { + yield return CreateArgInfo(arg); + } + } + + private static CSharpArgumentInfo CreateArgInfo(object arg) + { + var flags = CSharpArgumentInfoFlags.None; + if (arg != null) + { + flags |= CSharpArgumentInfoFlags.UseCompileTimeType; + if (arg is HostObject hostObject) + { + if ((hostObject.Type == typeof(int)) || (hostObject.Type.IsValueType && hostObject.Target.IsZero())) + { + flags |= CSharpArgumentInfoFlags.Constant; + } + } + else if (arg is HostVariable hostVariable) + { + if ((hostVariable.Type == typeof(int)) || (hostVariable.Type.IsValueType && hostVariable.Target.IsZero())) + { + flags |= CSharpArgumentInfoFlags.Constant; + } + } + else if (arg is int || arg.IsZero()) + { + flags |= CSharpArgumentInfoFlags.Constant; + } + else if (arg is IOutArg) + { + flags |= CSharpArgumentInfoFlags.IsOut; + } + else if (arg is IRefArg) + { + flags |= CSharpArgumentInfoFlags.IsRef; + } + } + + return CSharpArgumentInfo.Create(flags, null); + } + + private static CSharpArgumentInfo CreateStaticTypeArgInfo() + { + return CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType, null); + } + + private MethodBindResult BindMethodUsingReflection(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs, object[] args, object[] bindArgs) + { + var candidates = GetReflectionCandidates(bindFlags, hostTarget, name, typeArgs).Distinct().ToArray(); + if (candidates.Length > 0) + { + try + { + var rawResult = TypeHelpers.BindToMember(this, candidates, bindFlags, args, bindArgs); + if (rawResult != null) + { + return MethodBindResult.Create(name, bindFlags, rawResult, hostTarget, args); + } + } + catch (AmbiguousMatchException) + { + return new MethodBindResult(() => new AmbiguousMatchException(MiscHelpers.FormatInvariant("The object has multiple methods named '{0}' that match the specified arguments", name))); + } + } + + return new MethodBindResult(() => new MissingMethodException(MiscHelpers.FormatInvariant("The object has no method named '{0}' that matches the specified arguments", name))); + } + + private IEnumerable GetReflectionCandidates(BindingFlags bindFlags, HostTarget hostTarget, string name, Type[] typeArgs) + { + foreach (var method in GetReflectionCandidates(bindFlags, hostTarget.Type, name, typeArgs)) + { + yield return method; + } + + if (!(hostTarget is HostType) && hostTarget.Type.IsInterface) + { + foreach (var interfaceType in hostTarget.Type.GetInterfaces()) + { + foreach (var method in GetReflectionCandidates(bindFlags, interfaceType, name, typeArgs)) + { + yield return method; + } + } + + foreach (var method in GetReflectionCandidates(bindFlags, typeof(object), name, typeArgs)) + { + yield return method; + } + } + } + + private IEnumerable GetReflectionCandidates(BindingFlags bindFlags, Type type, string name, Type[] typeArgs) + { + foreach (var method in type.GetScriptableMethods(this, name, bindFlags)) + { + MethodInfo tempMethod = null; + + if (method.ContainsGenericParameters) + { + try + { + tempMethod = method.MakeGenericMethod(typeArgs); + } + catch (ArgumentException) + { + continue; + } + catch (NotSupportedException) + { + continue; + } + } + else if (typeArgs.Length < 1) + { + tempMethod = method; + } + + if ((tempMethod != null) && !tempMethod.ContainsGenericParameters) + { + yield return tempMethod; + } + } + } + + #endregion + + #region unit test support + + internal static void ClearCoreBindCache() + { + coreBindCache.Clear(); + Interlocked.Exchange(ref coreBindCount, 0); + } + + internal static long GetCoreBindCount() + { + return Interlocked.Read(ref coreBindCount); + } + + #endregion + + #region Nested type: MethodBindResult + + private readonly ref struct MethodBindResult + { + private readonly HostTarget hostTarget; + private readonly MethodInfo method; + private readonly object[] args; + private readonly Func exceptionFactory; + + private static readonly MethodInfo[] reflectionMethods = + { + typeof(object).GetMethod("GetType"), + typeof(System.Runtime.InteropServices._Exception).GetMethod("GetType"), + typeof(Exception).GetMethod("GetType") + }; + + public MethodBindResult(HostTarget hostTarget, MethodInfo method, object[] args) + { + this.hostTarget = hostTarget; + this.method = method; + this.args = args; + exceptionFactory = null; + } + + public MethodBindResult(Func exceptionFactory) + { + hostTarget = null; + method = null; + args = null; + this.exceptionFactory = exceptionFactory; + } + + public static MethodBindResult Create(string name, BindingFlags bindFlags, object rawResult, HostTarget hostTarget, object[] args) + { + var method = rawResult as MethodInfo; + if (method != null) + { + if (method.IsStatic && !bindFlags.HasFlag(BindingFlags.Static)) + { + return new MethodBindResult(() => new InvalidOperationException(MiscHelpers.FormatInvariant("Cannot access static method '{0}' in non-static context", method.Name))); + } + + return new MethodBindResult(hostTarget, method, args); + } + + return new MethodBindResult((rawResult as Func) ?? (() => new NotSupportedException(MiscHelpers.FormatInvariant("Invocation of method '{0}' failed (unrecognized binding)", name)))); + } + + public bool IsSuccess => method != null; + + public object RawResult => IsSuccess ? (object)method : exceptionFactory; + + public bool IsPreferredMethod(HostItem hostItem, string name) + { + return IsSuccess && IsUnblockedMethod(hostItem) && (method.GetScriptName(hostItem) == name); + } + + public bool IsUnblockedMethod(HostItem hostItem) + { + return IsSuccess && !method.IsBlockedFromScript(hostItem, hostItem.DefaultAccess); + } + + public object Invoke(HostItem hostItem) + { + if (!IsSuccess) + { + throw exceptionFactory(); + } + + bool isReflectionMethod = false; + for (int i = 0; i < reflectionMethods.Length; i++) + { + if (MemberComparer.Instance.Equals(reflectionMethods[i], method)) + { + isReflectionMethod = true; + break; + } + } + + if (isReflectionMethod) + { + hostItem.Engine.CheckReflection(); + } + + return InvokeHelpers.InvokeMethod(hostItem, method, hostTarget.InvokeTarget, args, method.GetScriptMemberFlags(hostItem)); + } + } + + #endregion + + #region Nested type: MethodBindingVisitor + + private sealed class MethodBindingVisitor : ExpressionVisitor + { + private readonly object target; + private readonly string name; + private readonly List results = new List(); + + public MethodBindingVisitor(object target, string name, Expression expression) + { + this.target = target; + this.name = name; + + Visit(expression); + if (results.Count != 1) + { + results.Clear(); + AddResult(() => new NotSupportedException(MiscHelpers.FormatInvariant("Invocation of method '{0}' failed (unrecognized binding)", name))); + } + else + { + var method = results[0] as MethodInfo; + if (method != null) + { + Debug.Assert(method.Name == name); + } + } + } + + public object Result => results[0]; + + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (node.Method.Name == name) + { + AddResult(node.Method); + } + + return base.VisitMethodCall(node); + } + + protected override Expression VisitInvocation(InvocationExpression node) + { + if (target is Delegate targetDelegate) + { + var del = DynamicHelpers.Invoke(node.Expression) as Delegate; + if (del == targetDelegate) + { + AddResult(del.GetType().GetMethod("Invoke")); + } + } + + return base.VisitInvocation(node); + } + + protected override Expression VisitUnary(UnaryExpression node) + { + if (node.NodeType == ExpressionType.Throw) + { + if (DynamicHelpers.Invoke(node.Operand) is Exception) + { + AddResult(() => (Exception)DynamicHelpers.Invoke(node.Operand)); + } + } + + return base.VisitUnary(node); + } + + private void AddResult(MethodInfo method) + { + results.Add(method); + } + + private void AddResult(Func exceptionFactory) + { + results.Add(exceptionFactory); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostItem.InvokeMethod.cs.meta b/Unity/Package/Runtime/HostItem.InvokeMethod.cs.meta new file mode 100644 index 000000000..7d0019ed2 --- /dev/null +++ b/Unity/Package/Runtime/HostItem.InvokeMethod.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1acc933f2d239c3449bb880f2db3ca5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostItem.NetStandard.cs b/Unity/Package/Runtime/HostItem.NetStandard.cs new file mode 100644 index 000000000..8161bd6d0 --- /dev/null +++ b/Unity/Package/Runtime/HostItem.NetStandard.cs @@ -0,0 +1,480 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Expando; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript +{ + internal partial class HostItem + { + #region initialization + + private static HostItem Create(ScriptEngine engine, HostTarget target, HostItemFlags flags) + { + if (!MiscHelpers.PlatformIsWindows()) + { + return new HostItem(engine, target, flags); + } + + return (TargetSupportsExpandoMembers(target, flags) && (engine is IWindowsScriptEngineTag)) ? new DispatchExHostItem(engine, target, flags) : new HostItem(engine, target, flags); + } + + #endregion + + #region internal members + + #region member invocation + + private object CreateAsyncEnumerator(IEnumerable enumerable) + { + return HostObject.Wrap(enumerable.GetEnumerator().ToScriptableAsyncEnumerator(Engine), typeof(IScriptableAsyncEnumerator)); + } + + private object CreateAsyncEnumerator() + { + if ((Target is HostObject) || (Target is IHostVariable) || (Target is IByRefArg)) + { + if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IAsyncEnumerable<>), out var typeArgs)) + { + var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess); + if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine))) + { + return enumerator; + } + } + else if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IEnumerable<>), out typeArgs)) + { + var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess); + if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine))) + { + return enumerator; + } + } + else if (BindSpecialTarget(out IEnumerable _)) + { + var helpersHostItem = Wrap(Engine, ScriptableEnumerableHelpers.HostType, HostItemFlags.PrivateAccess); + if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableAsyncEnumerator", this, Engine))) + { + return enumerator; + } + } + } + + throw new NotSupportedException("The object is not async-enumerable"); + } + + #endregion + + #endregion + + #region Nested type: DispatchExHostItem + + private sealed class DispatchExHostItem : ExpandoHostItem + { + #region data + + private static readonly Dictionary patchMap = new Dictionary(); + private readonly List expandoMembers = new List(); + + #endregion + + #region IDispatch[Ex] delegates + + private delegate int RawGetIDsOfNames( + [In] IntPtr pThis, + [In] ref Guid iid, + [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names, + [In] uint count, + [In] int lcid, + [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] int[] dispids + ); + + private delegate int RawGetDispID( + [In] IntPtr pThis, + [In] [MarshalAs(UnmanagedType.BStr)] string name, + [In] DispatchNameFlags flags, + [Out] out int dispid + ); + + private delegate int RawDeleteMemberByName( + [In] IntPtr pThis, + [In] [MarshalAs(UnmanagedType.BStr)] string name, + [In] DispatchNameFlags flags + ); + + private delegate int RawDeleteMemberByDispID( + [In] IntPtr pThis, + [In] int dispid + ); + + private delegate int RawGetMemberProperties( + [In] IntPtr pThis, + [In] int dispid, + [In] DispatchPropFlags fetchFlags, + [Out] out DispatchPropFlags flags + ); + + private delegate int RawGetMemberName( + [In] IntPtr pThis, + [In] int dispid, + [Out] [MarshalAs(UnmanagedType.BStr)] out string name + ); + + private delegate int RawGetNextDispID( + [In] IntPtr pThis, + [In] DispatchEnumFlags flags, + [In] int dispidCurrent, + [Out] out int dispidNext + ); + + #endregion + + #region constructors + + public DispatchExHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags) + : base(engine, target, flags) + { + EnsurePatched(); + } + + #endregion + + #region internal members + + private IEnumerable ReflectMembers + { + get + { + var members = ThisReflect.GetMembers(GetCommonBindFlags()); + if (members.Length > 0) + { + using (var unknownScope = Scope.Create(() => Marshal.GetIUnknownForObject(this), pUnknown => Marshal.Release(pUnknown))) + { + var pUnknown = unknownScope.Value; + using (var dispatchScope = Scope.Create(() => UnknownHelpers.QueryInterface(pUnknown), pDispatch => Marshal.Release(pDispatch))) + { + var pDispatch = dispatchScope.Value; + var getIDsOfNames = VTableHelpers.GetMethodDelegate(pDispatch, 5); + + var iid = Guid.Empty; + var names = new string[1]; + var dispids = new int[1]; + + for (var index = 0; index < members.Length; index++) + { + names[0] = members[index].Name; + if (HResult.Succeeded(getIDsOfNames(pDispatch, ref iid, names, 1, 0, dispids))) + { + yield return new Member { Name = names[0], DispID = dispids[0], DispIDName = MiscHelpers.GetDispIDName(dispids[0]) }; + } + } + } + } + } + } + } + + private IExpando ThisExpando => this; + + private void EnsurePatched() + { + using (var unknownScope = Scope.Create(() => Marshal.GetIUnknownForObject(this), pUnknown => Marshal.Release(pUnknown))) + { + var pUnknown = unknownScope.Value; + using (var dispatchExScope = Scope.Create(() => UnknownHelpers.QueryInterface(pUnknown), pDispatchEx => Marshal.Release(pDispatchEx))) + { + lock (VTablePatcher.PatchLock) + { + var pDispatchEx = dispatchExScope.Value; + var pVTable = Marshal.ReadIntPtr(pDispatchEx); + + if (!patchMap.ContainsKey(pVTable)) + { + var entry = new PatchEntry(); + + var origGetDispID = VTableHelpers.GetMethodDelegate(pDispatchEx, 7); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 7, new RawGetDispID((IntPtr pThis, string name, DispatchNameFlags nameFlags, out int dispid) => + { + try + { + return (Marshal.GetObjectForIUnknown(pThis) is DispatchExHostItem item) ? item.GetDispID(name, nameFlags, out dispid) : origGetDispID(pThis, name, nameFlags, out dispid); + } + catch (Exception exception) + { + dispid = SpecialDispIDs.Unknown; + return exception.HResult; + } + }))); + + var origDeleteMemberByName = VTableHelpers.GetMethodDelegate(pDispatchEx, 9); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 9, new RawDeleteMemberByName((pThis, name, nameFlags) => + { + try + { + return (Marshal.GetObjectForIUnknown(pThis) is DispatchExHostItem item) ? item.DeleteMemberByName(name, nameFlags) : origDeleteMemberByName(pThis, name, nameFlags); + } + catch (Exception exception) + { + return exception.HResult; + } + }))); + + var origDeleteMemberByDispID = VTableHelpers.GetMethodDelegate(pDispatchEx, 10); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 10, new RawDeleteMemberByDispID((pThis, dispid) => + { + try + { + return (Marshal.GetObjectForIUnknown(pThis) is DispatchExHostItem item) ? item.DeleteMemberByDispID(dispid) : origDeleteMemberByDispID(pThis, dispid); + } + catch (Exception exception) + { + return exception.HResult; + } + }))); + + var origGetMemberProperties = VTableHelpers.GetMethodDelegate(pDispatchEx, 11); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 11, new RawGetMemberProperties((IntPtr pThis, int dispid, DispatchPropFlags fetchFlags, out DispatchPropFlags propFlags) => + { + try + { + var item = Marshal.GetObjectForIUnknown(pThis) as DispatchExHostItem; + if (item == null) + { + return origGetMemberProperties(pThis, dispid, fetchFlags, out propFlags); + } + + var result = item.GetMemberProperties(dispid, fetchFlags, out propFlags); + if (result == HResult.DISP_E_MEMBERNOTFOUND) + { + return origGetMemberProperties(pThis, dispid, fetchFlags, out propFlags); + } + + return result; + } + catch (Exception exception) + { + propFlags = 0; + return exception.HResult; + } + }))); + + var origGetMemberName = VTableHelpers.GetMethodDelegate(pDispatchEx, 12); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 12, new RawGetMemberName((IntPtr pThis, int dispid, out string name) => + { + try + { + return (Marshal.GetObjectForIUnknown(pThis) is DispatchExHostItem item) ? item.GetMemberName(dispid, out name) : origGetMemberName(pThis, dispid, out name); + } + catch (Exception exception) + { + name = null; + return exception.HResult; + } + }))); + + var origGetNextDispID = VTableHelpers.GetMethodDelegate(pDispatchEx, 13); + entry.AddDelegate(VTableHelpers.SetMethodDelegate(pDispatchEx, 13, new RawGetNextDispID((IntPtr pThis, DispatchEnumFlags enumFlags, int dispidCurrent, out int dispidNext) => + { + try + { + return (Marshal.GetObjectForIUnknown(pThis) is DispatchExHostItem item) ? item.GetNextDispID(dispidCurrent, out dispidNext) : origGetNextDispID(pThis, enumFlags, dispidCurrent, out dispidNext); + } + catch (Exception exception) + { + dispidNext = SpecialDispIDs.Unknown; + return exception.HResult; + } + }))); + + patchMap.Add(pVTable, entry); + Debug.Assert(patchMap.Count < 16); + } + } + } + } + } + + #endregion + + #region HostItem overrides + + protected override string AdjustInvokeName(string name) + { + var member = expandoMembers.FirstOrDefault(expandoMember => name == expandoMember.DispIDName); + if (!member.IsDefault) + { + return member.Name; + } + + return name; + } + + protected override void AddExpandoMemberName(string name) + { + var dispid = 1; + + var dispids = ReflectMembers.Concat(expandoMembers).Select(member => member.DispID).ToArray(); + for (; dispids.Contains(dispid); dispid++) + { + if (dispid >= int.MaxValue) + { + throw new NotSupportedException("The object cannot support additional dynamic members"); + } + } + + base.AddExpandoMemberName(name); + expandoMembers.Add(new Member { Name = name, DispID = dispid, DispIDName = MiscHelpers.GetDispIDName(dispid) }); + } + + protected override void RemoveExpandoMemberName(string name) + { + base.RemoveExpandoMemberName(name); + + var index = expandoMembers.FindIndex(member => member.Name == name); + if (index >= 0) + { + expandoMembers.RemoveAt(index); + } + } + + #endregion + + #region IDispatchEx patches + + private int GetDispID(string name, DispatchNameFlags nameFlags, out int dispid) + { + var nameComparison = nameFlags.HasFlag(DispatchNameFlags.CaseInsensitive) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + + var member = ReflectMembers.Concat(expandoMembers).FirstOrDefault(testMember => string.Equals(testMember.Name, name, nameComparison)); + if (!member.IsDefault) + { + dispid = member.DispID; + return HResult.S_OK; + } + + if (nameFlags.HasFlag(DispatchNameFlags.Ensure)) + { + ThisExpando.AddProperty(name); + return GetDispID(name, nameFlags & ~DispatchNameFlags.Ensure, out dispid); + } + + dispid = SpecialDispIDs.Unknown; + return HResult.DISP_E_UNKNOWNNAME; + } + + private int DeleteMemberByName(string name, DispatchNameFlags nameFlags) + { + var nameComparison = nameFlags.HasFlag(DispatchNameFlags.CaseInsensitive) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + + var member = ReflectMembers.Concat(expandoMembers).FirstOrDefault(testMember => string.Equals(testMember.Name, name, nameComparison)); + if (!member.IsDefault && RemoveMember(member.Name)) + { + return HResult.S_OK; + } + + // IDispatchEx specifies S_FALSE, but DISP_E_UNKNOWNNAME provides parity with .NET Framework CCWs + return HResult.DISP_E_UNKNOWNNAME; + } + + private int DeleteMemberByDispID(int dispid) + { + var member = ReflectMembers.Concat(expandoMembers).FirstOrDefault(testMember => testMember.DispID == dispid); + if (!member.IsDefault && RemoveMember(member.Name)) + { + return HResult.S_OK; + } + + // IDispatchEx specifies S_FALSE, but DISP_E_UNKNOWNNAME provides parity with .NET Framework CCWs + return HResult.DISP_E_UNKNOWNNAME; + } + + private int GetMemberProperties(int dispid, DispatchPropFlags fetchFlags, out DispatchPropFlags propFlags) + { + var member = expandoMembers.FirstOrDefault(testMember => testMember.DispID == dispid); + if (!member.IsDefault) + { + propFlags = + DispatchPropFlags.CanGet | + DispatchPropFlags.CanPut | + DispatchPropFlags.CannotPutRef | + DispatchPropFlags.CannotCall | + DispatchPropFlags.CannotConstruct | + DispatchPropFlags.CannotSourceEvents; + + propFlags = propFlags & fetchFlags; + return HResult.S_OK; + } + + propFlags = 0; + return HResult.DISP_E_MEMBERNOTFOUND; + } + + private int GetMemberName(int dispid, out string name) + { + var member = ReflectMembers.Concat(expandoMembers).OrderBy(testMember => testMember.DispID).FirstOrDefault(testMember => testMember.DispID == dispid); + if (!member.IsDefault) + { + name = member.Name; + return HResult.S_OK; + } + + name = null; + return HResult.S_FALSE; + } + + private int GetNextDispID(int dispidCurrent, out int dispidNext) + { + var member = ReflectMembers.Concat(expandoMembers).OrderBy(testMember => testMember.DispID).FirstOrDefault(testMember => testMember.DispID > dispidCurrent); + if (!member.IsDefault) + { + dispidNext = member.DispID; + return HResult.S_OK; + } + + dispidNext = SpecialDispIDs.Default; + return HResult.S_FALSE; + } + + #endregion + + #region Nested type: PatchEntry + + private sealed class PatchEntry + { + // ReSharper disable once CollectionNeverQueried.Local + private readonly List delegates = new List(); + + public void AddDelegate(Delegate del) + { + delegates.Add(del); + } + } + + #endregion + + #region Nested type: Member + + private struct Member + { + public string Name; + public int DispID; + public string DispIDName; + + public bool IsDefault => DispID == SpecialDispIDs.Default; + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostItem.NetStandard.cs.meta b/Unity/Package/Runtime/HostItem.NetStandard.cs.meta new file mode 100644 index 000000000..249fa5e5b --- /dev/null +++ b/Unity/Package/Runtime/HostItem.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f4f93f11b4cb314192f10e28d4d50e5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostItem.cs b/Unity/Package/Runtime/HostItem.cs new file mode 100644 index 000000000..c2dead932 --- /dev/null +++ b/Unity/Package/Runtime/HostItem.cs @@ -0,0 +1,2505 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Runtime.InteropServices.Expando; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript +{ + internal partial class HostItem : DynamicObject, IReflect, IDynamic, IEnumVARIANT, ICustomQueryInterface, IScriptMarshalWrapper, IHostTargetContext + { + #region data + + private HostTargetMemberData targetMemberData; + + private static readonly PropertyInfo[] reflectionProperties = + { + typeof(Delegate).GetProperty("Method"), + typeof(Exception).GetProperty("TargetSite") + }; + + internal static bool EnableVTablePatching; + [ThreadStatic] private static bool bypassVTablePatching; + + #endregion + + #region constructors + + private HostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags) + { + Engine = engine; + Target = target; + Flags = flags; + + BindSpecialTarget(); + BindTargetMemberData(); + } + + #endregion + + #region wrappers + + public static object Wrap(ScriptEngine engine, object obj) + { + return Wrap(engine, obj, null, HostItemFlags.None); + } + + public static object Wrap(ScriptEngine engine, object obj, Type type) + { + return Wrap(engine, obj, type, HostItemFlags.None); + } + + public static object Wrap(ScriptEngine engine, object obj, HostItemFlags flags) + { + return Wrap(engine, obj, null, flags); + } + + private static object Wrap(ScriptEngine engine, object obj, Type type, HostItemFlags flags) + { + if (obj == null) + { + return null; + } + + if (obj is HostItem hostItem) + { + obj = hostItem.Target; + } + + if (obj is HostTarget hostTarget) + { + return BindOrCreate(engine, hostTarget, flags); + } + + if (type == null) + { + type = obj.GetTypeOrTypeInfo(); + } + else + { + Debug.Assert(type.IsInstanceOfType(obj)); + } + + if (obj is Enum) + { + return BindOrCreate(engine, obj, type, flags); + } + + var typeCode = Type.GetTypeCode(type); + if ((typeCode == TypeCode.Object) || (typeCode == TypeCode.DateTime)) + { + return BindOrCreate(engine, obj, type, flags); + } + + return obj; + } + + #endregion + + #region public members + + public delegate HostItem CreateFunc(ScriptEngine engine, HostTarget target, HostItemFlags flags); + + public HostTarget Target { get; } + + public HostItemFlags Flags { get; } + + public Invocability Invocability + { + get + { + if (TargetInvocability == null) + { + TargetInvocability = Target.GetInvocability(this, GetCommonBindFlags(), Flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers)); + } + + return TargetInvocability.GetValueOrDefault(); + } + } + + public object InvokeMember(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, CultureInfo culture, bool bypassTunneling) + { + return InvokeMember(name, invokeFlags, args, bindArgs, culture, bypassTunneling, out _); + } + + public object InvokeMember(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, CultureInfo culture, bool bypassTunneling, out bool isCacheable) + { + name = AdjustInvokeName(name); + AdjustInvokeFlags(ref invokeFlags); + + isCacheable = false; + + if (Target.TryInvokeAuxMember(this, name, invokeFlags, args, bindArgs, out var result)) + { + if (Target is IHostVariable) + { + // the variable may have been reassigned + BindSpecialTarget(); + } + + return result; + } + + if (TargetDynamic != null) + { + return InvokeDynamicMember(name, invokeFlags, args); + } + + if (TargetPropertyBag != null) + { + return InvokePropertyBagMember(name, invokeFlags, args, bindArgs); + } + + if (TargetList != null) + { + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + return InvokeListElement(index, invokeFlags, args, bindArgs); + } + } + + if (!bypassTunneling) + { + int testLength; + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) + { + testLength = invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) ? 0 : -1; + } + else + { + testLength = invokeFlags.HasFlagNonAlloc(BindingFlags.SetField) ? 1 : 0; + } + + if ((args.Length > testLength) && (name != SpecialMemberNames.Default)) + { + var value = GetHostProperty(name, GetCommonBindFlags(), ArrayHelpers.GetEmptyArray(), ArrayHelpers.GetEmptyArray(), false, out _); + if (!(value is Nonexistent)) + { + if (Engine.MarshalToScript(value) is HostItem hostItem) + { + return hostItem.InvokeMember(SpecialMemberNames.Default, invokeFlags, args, bindArgs, culture, true, out isCacheable); + } + } + } + } + + return InvokeHostMember(name, invokeFlags, args, bindArgs, out isCacheable); + } + + #endregion + + #region internal members + + #region interface accessors + + private IReflect ThisReflect => this; + + private IDynamic ThisDynamic => this; + + #endregion + + #region collateral accessors + + private IDynamic TargetDynamic => Collateral.TargetDynamic.Get(this); + + private IPropertyBag TargetPropertyBag + { + get => Collateral.TargetPropertyBag.Get(this); + set => Collateral.TargetPropertyBag.Set(this, value); + } + + private IHostList TargetList + { + get => Collateral.TargetList.Get(this); + set => Collateral.TargetList.Set(this, value); + } + + private DynamicHostMetaObject TargetDynamicMetaObject + { + get => Collateral.TargetDynamicMetaObject.Get(this); + set => Collateral.TargetDynamicMetaObject.Set(this, value); + } + + private IEnumerator TargetEnumerator => Collateral.TargetEnumerator.Get(this); + + private HashSet ExpandoMemberNames + { + get => Collateral.ExpandoMemberNames.Get(this); + set => Collateral.ExpandoMemberNames.Set(this, value); + } + + private Dictionary HostMethodMap + { + get => Collateral.HostMethodMap.Get(this); + set => Collateral.HostMethodMap.Set(this, value); + } + + private Dictionary HostIndexedPropertyMap + { + get => Collateral.HostIndexedPropertyMap.Get(this); + set => Collateral.HostIndexedPropertyMap.Set(this, value); + } + + private int[] PropertyIndices + { + get => Collateral.ListData.GetOrCreate(this).PropertyIndices; + set => Collateral.ListData.GetOrCreate(this).PropertyIndices = value; + } + + private int CachedListCount + { + get => Collateral.ListData.GetOrCreate(this).CachedCount; + set => Collateral.ListData.GetOrCreate(this).CachedCount = value; + } + + private HostItemCollateral Collateral => Engine.HostItemCollateral; + + #endregion + + #region target member data accessors + + private string[] TypeEventNames + { + get => targetMemberData.TypeEventNames; + set => targetMemberData.TypeEventNames = value; + } + + private string[] TypeFieldNames + { + get => targetMemberData.TypeFieldNames; + set => targetMemberData.TypeFieldNames = value; + } + + private string[] TypeMethodNames + { + get => targetMemberData.TypeMethodNames; + set => targetMemberData.TypeMethodNames = value; + } + + private string[] TypePropertyNames + { + get => targetMemberData.TypePropertyNames; + set => targetMemberData.TypePropertyNames = value; + } + + private string[] AllFieldNames + { + get => targetMemberData.AllFieldNames; + set => targetMemberData.AllFieldNames = value; + } + + private string[] AllMethodNames + { + get => targetMemberData.AllMethodNames; + set => targetMemberData.AllMethodNames = value; + } + + private string[] OwnMethodNames + { + get => targetMemberData.OwnMethodNames; + set => targetMemberData.OwnMethodNames = value; + } + + private string[] EnumeratedMethodNames => Engine.EnumerateInstanceMethods ? (Engine.EnumerateExtensionMethods ? AllMethodNames : OwnMethodNames) : ArrayHelpers.GetEmptyArray(); + + private string[] AllPropertyNames + { + get => targetMemberData.AllPropertyNames; + set => targetMemberData.AllPropertyNames = value; + } + + private string[] AllMemberNames + { + get => targetMemberData.AllMemberNames; + set => targetMemberData.AllMemberNames = value; + } + + private FieldInfo[] AllFields + { + get => targetMemberData.AllFields; + set => targetMemberData.AllFields = value; + } + + private MethodInfo[] AllMethods + { + get => targetMemberData.AllMethods; + set => targetMemberData.AllMethods = value; + } + + private PropertyInfo[] AllProperties + { + get => targetMemberData.AllProperties; + set => targetMemberData.AllProperties = value; + } + + private object EnumerationSettingsToken + { + get => targetMemberData.EnumerationSettingsToken; + set => targetMemberData.EnumerationSettingsToken = value; + } + + private ExtensionMethodSummary ExtensionMethodSummary + { + get => targetMemberData.ExtensionMethodSummary; + set => targetMemberData.ExtensionMethodSummary = value; + } + + private Invocability? TargetInvocability + { + get => targetMemberData.TargetInvocability; + set => targetMemberData.TargetInvocability = value; + } + + private CustomAttributeLoader CurrentCustomAttributeLoader => Engine.CustomAttributeLoader; + + private Type CurrentAccessContext => Flags.HasFlagNonAlloc(HostItemFlags.PrivateAccess) ? Target.Type : Engine.AccessContext; + + private ScriptAccess CurrentDefaultAccess => Engine.DefaultAccess; + + private HostTargetFlags CurrentTargetFlags => Target.GetFlags(this); + + private CustomAttributeLoader CachedCustomAttributeLoader => (targetMemberData is HostTargetMemberDataWithContext targetMemberDataWithContext) ? targetMemberDataWithContext.CustomAttributeLoader : CurrentCustomAttributeLoader; + + private Type CachedAccessContext => (targetMemberData is HostTargetMemberDataWithContext targetMemberDataWithContext) ? targetMemberDataWithContext.AccessContext : CurrentAccessContext; + + private ScriptAccess CachedDefaultAccess + { + get + { + var targetMemberDataWithContext = targetMemberData as HostTargetMemberDataWithContext; + return targetMemberDataWithContext?.DefaultAccess ?? CurrentDefaultAccess; + } + } + + private HostTargetFlags CachedTargetFlags + { + get + { + var targetMemberDataWithContext = targetMemberData as HostTargetMemberDataWithContext; + return targetMemberDataWithContext?.TargetFlags ?? CurrentTargetFlags; + } + } + + #endregion + + #region initialization + + private static bool TargetSupportsExpandoMembers(HostTarget target, HostItemFlags flags) + { + if (!TargetSupportsSpecialTargets(target)) + { + return false; + } + + if (typeof(IDynamic).IsAssignableFrom(target.Type)) + { + return true; + } + + if (target is IHostVariable) + { + if (target.Type.IsImport) + { + return true; + } + } + else + { + if ((target.InvokeTarget is IDispatchEx dispatchEx) && dispatchEx.GetType().IsCOMObject) + { + return true; + } + } + + if (typeof(IPropertyBag).IsAssignableFrom(target.Type)) + { + return true; + } + + if (!flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers) && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(target.Type)) + { + return true; + } + + return false; + } + + private bool CanAddExpandoMembers() + { + return (TargetDynamic != null) || ((TargetPropertyBag != null) && !TargetPropertyBag.IsReadOnly) || (TargetDynamicMetaObject != null); + } + + private static object BindOrCreate(ScriptEngine engine, object target, Type type, HostItemFlags flags) + { + return BindOrCreate(engine, HostObject.Wrap(target, type), flags); + } + + private static object BindOrCreate(ScriptEngine engine, HostTarget target, HostItemFlags flags) + { + return engine.GetOrCreateHostItem(target, flags, Create); + } + + private void BindSpecialTarget() + { + if (TargetSupportsSpecialTargets(Target)) + { + if (BindSpecialTarget(Collateral.TargetDynamic)) + { + TargetPropertyBag = null; + TargetList = null; + TargetDynamicMetaObject = null; + } + else if (BindSpecialTarget(Collateral.TargetPropertyBag)) + { + TargetList = null; + TargetDynamicMetaObject = null; + } + else + { + if (!Flags.HasFlagNonAlloc(HostItemFlags.HideDynamicMembers) && BindSpecialTarget(out IDynamicMetaObjectProvider dynamicMetaObjectProvider)) + { + var dynamicMetaObject = dynamicMetaObjectProvider.GetMetaObject(Expression.Constant(Target.InvokeTarget)); + TargetDynamicMetaObject = new DynamicHostMetaObject(dynamicMetaObjectProvider, dynamicMetaObject); + TargetList = null; + } + else + { + TargetDynamicMetaObject = null; + BindSpecialTarget(Collateral.TargetList); + } + } + } + } + + private bool BindSpecialTarget(CollateralObject property) where T : class + { + if (BindSpecialTarget(out T value)) + { + property.Set(this, value); + return true; + } + + property.Clear(this); + return false; + } + + private bool BindSpecialTarget(out T specialTarget) where T : class + { + if (Target.InvokeTarget == null) + { + specialTarget = null; + return false; + } + + if (typeof(T) == typeof(IDynamic)) + { + // provide fully dynamic behavior for exposed IDispatch[Ex] implementations + + if ((Target.InvokeTarget is IDispatchEx dispatchEx) && Target.Type.IsUnknownCOMObject()) + { + specialTarget = (T)(object)(new DynamicDispatchExWrapper(this, dispatchEx)); + return true; + } + + if ((Target.InvokeTarget is IDispatch dispatch) && Target.Type.IsUnknownCOMObject()) + { + specialTarget = (T)(object)(new DynamicDispatchWrapper(this, dispatch)); + return true; + } + } + else if (typeof(T) == typeof(IHostList)) + { + // generic list support + + if (Target.Type.IsAssignableToGenericType(typeof(IList<>), out var typeArgs)) + { + if (typeof(IList).IsAssignableFrom(Target.Type)) + { + specialTarget = new HostList(Engine, (IList)Target.InvokeTarget, typeArgs[0]) as T; + return specialTarget != null; + } + + specialTarget = typeof(HostList<>).MakeGenericType(typeArgs).CreateInstance(Engine, Target.InvokeTarget) as T; + return specialTarget != null; + } + + if (typeof(IList).IsAssignableFrom(Target.Type)) + { + specialTarget = new HostList(Engine, (IList)Target.InvokeTarget, typeof(object)) as T; + return specialTarget != null; + } + + if (Target.Type.IsAssignableToGenericType(typeof(IReadOnlyList<>), out typeArgs)) + { + specialTarget = typeof(ReadOnlyHostList<>).MakeGenericType(typeArgs).CreateInstance(Engine, Target.InvokeTarget) as T; + return specialTarget != null; + } + + specialTarget = null; + return false; + } + + // The check here is required because the item may be bound to a specific target base + // class or interface - one that must not trigger special treatment. + + if (typeof(T).IsAssignableFrom(Target.Type)) + { + specialTarget = Target.InvokeTarget as T; + return specialTarget != null; + } + + specialTarget = null; + return false; + } + + private void BindTargetMemberData() + { + if ((targetMemberData == null) || (CustomAttributeLoader != CurrentCustomAttributeLoader) || (AccessContext != CurrentAccessContext) || (DefaultAccess != CurrentDefaultAccess) || (TargetFlags != CurrentTargetFlags)) + { + if (Target is HostMethod) + { + // host methods can share their (dummy) member data + targetMemberData = Engine.SharedHostMethodMemberData; + return; + } + + if (Target is HostIndexedProperty) + { + // host indexed properties can share their (dummy) member data + targetMemberData = Engine.SharedHostIndexedPropertyMemberData; + return; + } + + if (Target is ScriptMethod) + { + // script methods can share their (dummy) member data + targetMemberData = Engine.SharedScriptMethodMemberData; + return; + } + + if (Target is HostObject hostObject) + { + if ((TargetDynamic == null) && (TargetPropertyBag == null) && (TargetList == null) && (TargetDynamicMetaObject == null)) + { + // host objects without dynamic members can share their member data + targetMemberData = Engine.GetSharedHostObjectMemberData(hostObject, CurrentCustomAttributeLoader, CurrentAccessContext, CurrentDefaultAccess, CurrentTargetFlags); + return; + } + } + + // all other targets use unique member data + targetMemberData = new HostTargetMemberDataWithContext(CurrentCustomAttributeLoader, CurrentAccessContext, CurrentDefaultAccess, CurrentTargetFlags); + } + } + + private static bool TargetSupportsSpecialTargets(HostTarget target) + { + return (target is HostObject) || (target is IHostVariable) || (target is IByRefArg); + } + + #endregion + + #region member data maintenance + + private string[] GetLocalEventNames() + { + if (TypeEventNames == null) + { + var localEvents = Target.Type.GetScriptableEvents(this, GetCommonBindFlags()); + TypeEventNames = localEvents.Select(eventInfo => eventInfo.GetScriptName(this)).ToArray(); + } + + return TypeEventNames; + } + + private string[] GetLocalFieldNames() + { + if (TypeFieldNames == null) + { + var localFields = Target.Type.GetScriptableFields(this, GetCommonBindFlags()); + TypeFieldNames = localFields.Select(field => field.GetScriptName(this)).ToArray(); + } + + return TypeFieldNames; + } + + private string[] GetLocalMethodNames() + { + if (TypeMethodNames == null) + { + var localMethods = Target.Type.GetScriptableMethods(this, GetMethodBindFlags()); + TypeMethodNames = localMethods.Select(method => method.GetScriptName(this)).ToArray(); + } + + return TypeMethodNames; + } + + private string[] GetLocalPropertyNames() + { + if (TypePropertyNames == null) + { + var localProperties = Target.Type.GetScriptableProperties(this, GetCommonBindFlags()); + TypePropertyNames = localProperties.Select(property => property.GetScriptName(this)).ToArray(); + } + + return TypePropertyNames; + } + + private string[] GetAllFieldNames() + { + if ((TargetDynamic == null) && (TargetPropertyBag == null)) + { + return GetLocalFieldNames().Concat(GetLocalEventNames()).Distinct().ToArray(); + } + + return ArrayHelpers.GetEmptyArray(); + } + + private string[] GetAllMethodNames(out string[] ownMethodNames) + { + ownMethodNames = null; + + var names = Target.GetAuxMethodNames(this, GetMethodBindFlags()).AsEnumerable() ?? Enumerable.Empty(); + if ((TargetDynamic == null) && (TargetPropertyBag == null)) + { + names = names.Concat(GetLocalMethodNames()); + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowExtensionMethods)) + { + var extensionMethodSummary = Engine.ExtensionMethodSummary; + ExtensionMethodSummary = extensionMethodSummary; + + var extensionMethodNames = extensionMethodSummary.MethodNames; + if (extensionMethodNames.Length > 0) + { + ownMethodNames = names.Distinct().ToArray(); + names = ownMethodNames.Concat(extensionMethodNames); + } + } + } + + var result = names.Distinct().ToArray(); + if (ownMethodNames == null) + { + ownMethodNames = result; + } + + return result; + } + + private string[] GetAllPropertyNames() + { + var names = Target.GetAuxPropertyNames(this, GetCommonBindFlags()).AsEnumerable() ?? Enumerable.Empty(); + if (TargetDynamic != null) + { + names = names.Concat(TargetDynamic.GetPropertyNames()); + names = names.Concat(TargetDynamic.GetPropertyIndices().Select(index => index.ToString(CultureInfo.InvariantCulture))); + } + else if (TargetPropertyBag != null) + { + names = names.Concat(TargetPropertyBag.Keys); + } + else + { + names = names.Concat(GetLocalPropertyNames()); + + if (TargetList != null) + { + CachedListCount = TargetList.Count; + if (CachedListCount > 0) + { + names = names.Concat(Enumerable.Range(0, CachedListCount).Select(index => index.ToString(CultureInfo.InvariantCulture))); + } + } + + if (TargetDynamicMetaObject != null) + { + names = names.Concat(TargetDynamicMetaObject.GetDynamicMemberNames()); + } + } + + if (ExpandoMemberNames != null) + { + names = names.Except(ExpandoMemberNames); + } + + return names.Distinct().ToArray(); + } + + private void UpdateFieldNames(out bool updated) + { + if (AllFieldNames == null) + { + AllFieldNames = GetAllFieldNames(); + updated = true; + } + else + { + updated = false; + } + } + + private void UpdateMethodNames(out bool updated) + { + if ((AllMethodNames == null) || + (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowExtensionMethods) && (ExtensionMethodSummary != Engine.ExtensionMethodSummary))) + { + AllMethodNames = GetAllMethodNames(out var ownMethodNames); + OwnMethodNames = ownMethodNames; + updated = true; + } + else + { + updated = false; + } + } + + private void UpdatePropertyNames(out bool updated) + { + if ((AllPropertyNames == null) || + (TargetDynamic != null) || + (TargetPropertyBag != null) || + (TargetDynamicMetaObject != null) || + ((TargetList != null) && (CachedListCount != TargetList.Count))) + { + AllPropertyNames = GetAllPropertyNames(); + updated = true; + } + else + { + updated = false; + } + } + + private void UpdateEnumerationSettingsToken(out bool updated) + { + var enumerationSettingsToken = Engine.EnumerationSettingsToken; + if (EnumerationSettingsToken != enumerationSettingsToken) + { + EnumerationSettingsToken = enumerationSettingsToken; + updated = true; + } + else + { + updated = false; + } + } + + protected virtual void AddExpandoMemberName(string name) + { + if (ExpandoMemberNames == null) + { + ExpandoMemberNames = new HashSet(); + } + + ExpandoMemberNames.Add(name); + } + + protected virtual void RemoveExpandoMemberName(string name) + { + ExpandoMemberNames?.Remove(name); + } + + #endregion + + #region member invocation + + private bool UseCaseInsensitiveMemberBinding => Engine.UseCaseInsensitiveMemberBinding; + + private StringComparison MemberNameComparison => UseCaseInsensitiveMemberBinding ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + + private StringComparer MemberNameComparer => UseCaseInsensitiveMemberBinding ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; + + private T HostInvoke(Func func) + { + BindTargetMemberData(); + return Engine.HostInvoke(func); + } + + private BindingFlags GetCommonBindFlags() + { + var bindFlags = BindingFlags.Public | BindingFlags.NonPublic; + + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowStaticMembers)) + { + bindFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; + } + + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowInstanceMembers)) + { + bindFlags |= BindingFlags.Instance; + } + + if (UseCaseInsensitiveMemberBinding) + { + bindFlags |= BindingFlags.IgnoreCase; + } + + return bindFlags; + } + + private BindingFlags GetMethodBindFlags() + { + return GetCommonBindFlags() | BindingFlags.OptionalParamBinding; + } + + protected virtual string AdjustInvokeName(string name) + { + return name; + } + + private void AdjustInvokeFlags(ref BindingFlags invokeFlags) + { + const BindingFlags onFlags = + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.OptionalParamBinding; + + const BindingFlags offFlags = + BindingFlags.DeclaredOnly | + BindingFlags.ExactBinding; + + const BindingFlags setPropertyFlags = + BindingFlags.SetProperty | + BindingFlags.PutDispProperty | + BindingFlags.PutRefDispProperty; + + invokeFlags |= onFlags; + invokeFlags &= ~offFlags; + + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowStaticMembers)) + { + invokeFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy; + } + else + { + invokeFlags &= ~BindingFlags.Static; + } + + if (TargetFlags.HasFlagNonAlloc(HostTargetFlags.AllowInstanceMembers)) + { + invokeFlags |= BindingFlags.Instance; + } + else + { + invokeFlags &= ~BindingFlags.Instance; + } + + if (UseCaseInsensitiveMemberBinding) + { + invokeFlags |= BindingFlags.IgnoreCase; + } + else + { + invokeFlags &= ~BindingFlags.IgnoreCase; + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetProperty)) + { + invokeFlags |= BindingFlags.GetField; + } + + if ((invokeFlags & setPropertyFlags) != 0) + { + invokeFlags |= BindingFlags.SetField; + } + } + + private object InvokeReflectMember(string name, BindingFlags invokeFlags, object[] wrappedArgs, CultureInfo culture, string[] namedParams) + { + return InvokeReflectMember(name, invokeFlags, wrappedArgs, culture, namedParams, out _); + } + + private object InvokeReflectMember(string name, BindingFlags invokeFlags, object[] wrappedArgs, CultureInfo culture, string[] namedParams, out bool isCacheable) + { + var resultIsCacheable = false; + var result = Engine.MarshalToScript(HostInvoke(() => + { + var args = Engine.MarshalToHost(wrappedArgs, false); + + var argOffset = 0; + if ((namedParams != null) && (namedParams.Length > 0) && (namedParams[0] == SpecialParamNames.This)) + { + args = args.Skip(1).ToArray(); + argOffset = 1; + } + + var bindArgs = args; + if ((args.Length > 0) && (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod) || invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance))) + { + bindArgs = Engine.MarshalToHost(wrappedArgs, true); + if (argOffset > 0) + { + bindArgs = bindArgs.Skip(argOffset).ToArray(); + } + + var savedArgs = (object[])args.Clone(); + var tempResult = InvokeMember(name, invokeFlags, args, bindArgs, culture, false, out resultIsCacheable); + + for (var index = 0; index < args.Length; index++) + { + var arg = args[index]; + if (!ReferenceEquals(arg, savedArgs[index])) + { + wrappedArgs[argOffset + index] = Engine.MarshalToScript(arg); + } + } + + return tempResult; + } + + return InvokeMember(name, invokeFlags, args, bindArgs, culture, false, out resultIsCacheable); + })); + + isCacheable = resultIsCacheable; + return result; + } + + private object InvokeDynamicMember(string name, BindingFlags invokeFlags, object[] args) + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance)) + { + if (name == SpecialMemberNames.Default) + { + return TargetDynamic.Invoke(true, args); + } + + throw new InvalidOperationException("Invalid constructor invocation"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) + { + if (name == SpecialMemberNames.Default) + { + try + { + return TargetDynamic.Invoke(false, args); + } + catch + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) && (args.Length < 1)) + { + return Target; + } + + throw; + } + } + + try + { + return TargetDynamic.InvokeMethod(name, args); + } + catch + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + return TargetDynamic.GetProperty(name, args); + } + + throw; + } + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + return TargetDynamic.GetProperty(name, args); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) + { + if (args.Length > 0) + { + TargetDynamic.SetProperty(name, args); + return args[args.Length - 1]; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + throw new InvalidOperationException("Invalid member invocation mode"); + } + + private object InvokePropertyBagMember(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs) + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) + { + object value; + + if (name == SpecialMemberNames.Default) + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + if (args.Length < 1) + { + return TargetPropertyBag; + } + + if (args.Length == 1) + { + return TargetPropertyBag.TryGetValue(Convert.ToString(args[0]), out value) ? value : Nonexistent.Value; + } + } + + throw new NotSupportedException("The object does not support the requested invocation operation"); + } + + if (name == SpecialMemberNames.NewEnum) + { + return CreateScriptableEnumerator(TargetPropertyBag); + } + + if (name == SpecialMemberNames.NewAsyncEnum) + { + return CreateAsyncEnumerator(TargetPropertyBag); + } + + if (!TargetPropertyBag.TryGetValue(name, out value)) + { + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no property named '{0}'", name)); + } + + if (InvokeHelpers.TryInvokeObject(this, value, invokeFlags, args, bindArgs, true, out var result)) + { + return result; + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + if (args.Length < 1) + { + return value; + } + + if (args.Length == 1) + { + if (value == null) + { + throw new InvalidOperationException("Cannot invoke a null property value"); + } + + return ((HostItem)Wrap(Engine, value)).InvokeMember(SpecialMemberNames.Default, invokeFlags, args, bindArgs, null, true); + } + } + + throw new NotSupportedException("The object does not support the requested invocation operation"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + if (name == SpecialMemberNames.Default) + { + if (args.Length == 1) + { + return TargetPropertyBag[Convert.ToString(args[0])]; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + if (name == SpecialMemberNames.NewEnum) + { + return CreateScriptableEnumerator(TargetPropertyBag); + } + + if (name == SpecialMemberNames.NewAsyncEnum) + { + return CreateAsyncEnumerator(TargetPropertyBag); + } + + if (args.Length < 1) + { + return TargetPropertyBag.TryGetValue(name, out var value) ? value : Nonexistent.Value; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) + { + if (name == SpecialMemberNames.Default) + { + if (args.Length == 2) + { + return TargetPropertyBag[Convert.ToString(args[0])] = args[1]; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + if (args.Length == 1) + { + return TargetPropertyBag[name] = args[0]; + } + + if (args.Length == 2) + { + if (TargetPropertyBag.TryGetValue(name, out var value)) + { + if (value == null) + { + throw new InvalidOperationException("Cannot invoke a null property value"); + } + + return ((HostItem)Wrap(Engine, value)).InvokeMember(SpecialMemberNames.Default, invokeFlags, args, bindArgs, null, true); + } + + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no property named '{0}'", name)); + } + + throw new InvalidOperationException("Invalid argument count"); + } + + throw new InvalidOperationException("Invalid member invocation mode"); + } + + private object InvokeListElement(int index, BindingFlags invokeFlags, object[] args, object[] bindArgs) + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) + { + if (InvokeHelpers.TryInvokeObject(this, TargetList[index], invokeFlags, args, bindArgs, true, out var result)) + { + return result; + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField) && (args.Length < 1)) + { + return TargetList[index]; + } + + throw new NotSupportedException("The object does not support the requested invocation operation"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + if (args.Length < 1) + { + return TargetList[index]; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) + { + if (args.Length == 1) + { + return TargetList[index] = args[0]; + } + + throw new InvalidOperationException("Invalid argument count"); + } + + throw new InvalidOperationException("Invalid member invocation mode"); + } + + private object InvokeHostMember(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out bool isCacheable) + { + isCacheable = false; + object result; + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.CreateInstance)) + { + if (name == SpecialMemberNames.Default) + { + if (Target is HostType hostType) + { + var typeArgs = GetTypeArgs(args).Select(HostType.Wrap).ToArray(); + if (typeArgs.Length > 0) + { + // ReSharper disable CoVariantArrayConversion + + if (hostType.TryInvoke(this, BindingFlags.InvokeMethod, typeArgs, typeArgs, out result)) + { + hostType = result as HostType; + if (hostType != null) + { + args = args.Skip(typeArgs.Length).ToArray(); + bindArgs = bindArgs.Skip(typeArgs.Length).ToArray(); + + var specificType = hostType.GetSpecificType(); + if (typeof(Delegate).IsAssignableFrom(specificType)) + { + if (args.Length != 1) + { + throw new InvalidOperationException("Invalid constructor invocation"); + } + + return DelegateFactory.CreateDelegate(Engine, args[0], specificType); + } + + return specificType.CreateInstance(this, Target, args, bindArgs); + } + } + + throw new InvalidOperationException("Invalid constructor invocation"); + + // ReSharper restore CoVariantArrayConversion + } + + var type = hostType.GetSpecificType(); + if (typeof(Delegate).IsAssignableFrom(type)) + { + if (args.Length != 1) + { + throw new InvalidOperationException("Invalid constructor invocation"); + } + + return DelegateFactory.CreateDelegate(Engine, args[0], type); + } + + return type.CreateInstance(this, Target, args, bindArgs); + } + + if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TryCreateInstance(args, out result)) + { + return result; + } + } + } + + throw new InvalidOperationException("Invalid constructor invocation"); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.InvokeMethod)) + { + if (name == SpecialMemberNames.Default) + { + if (InvokeHelpers.TryInvokeObject(this, Target, invokeFlags, args, bindArgs, TargetDynamicMetaObject != null, out result)) + { + return result; + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + result = GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); + if (!(result is Nonexistent)) + { + return result; + } + + if (args.Length < 1) + { + return Target; + } + + if (TargetDynamicMetaObject != null) + { + // dynamic target; don't throw for default indexed property retrieval failure + + return result; + } + } + + throw new NotSupportedException("The object does not support the requested invocation operation"); + } + + if (name == SpecialMemberNames.NewEnum) + { + return CreateScriptableEnumerator(); + } + + if (name == SpecialMemberNames.NewAsyncEnum) + { + return CreateAsyncEnumerator(); + } + + if ((TargetDynamicMetaObject != null) && TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlagNonAlloc(BindingFlags.IgnoreCase))) + { + if (TargetDynamicMetaObject.TryInvokeMember(this, name, invokeFlags, args, out result)) + { + return result; + } + } + + if (ThisReflect.GetMethods(GetMethodBindFlags()).Any(method => string.Equals(method.Name, name, MemberNameComparison))) + { + // The target appears to have a method with the right name, but it could be an + // extension method that fails to bind. If that happens, we should attempt the + // fallback but throw the original exception if the fallback fails as well. + + try + { + return InvokeMethod(name, args, bindArgs); + } + catch (TargetInvocationException) + { + throw; + } + catch + { + // ReSharper disable EmptyGeneralCatchClause + + try + { + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); + } + + } + catch (TargetInvocationException) + { + throw; + } + catch + { + } + + throw; + + // ReSharper restore EmptyGeneralCatchClause + } + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); + } + + throw new MissingMethodException(MiscHelpers.FormatInvariant("The object has no suitable method named '{0}'", name)); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.GetField)) + { + return GetHostProperty(name, invokeFlags, args, bindArgs, true, out isCacheable); + } + + if (invokeFlags.HasFlagNonAlloc(BindingFlags.SetField)) + { + return SetHostProperty(name, invokeFlags, args, bindArgs); + } + + throw new InvalidOperationException("Invalid member invocation mode"); + } + + private object GetHostProperty(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, bool includeBoundMembers, out bool isCacheable) + { + isCacheable = false; + + var signature = new BindSignature(AccessContext, invokeFlags, Target, name, ArrayHelpers.GetEmptyArray(), bindArgs); + if (Engine.TryGetCachedPropertyGetBindResult(signature, out var boundMember)) + { + if (boundMember is PropertyInfo boundProperty) + { + return GetHostPropertyWorker(boundProperty, boundProperty.GetMethod, args); + } + + if (boundMember is FieldInfo boundField) + { + return GetHostFieldWorker(boundField, out isCacheable); + } + } + + if (name == SpecialMemberNames.Default) + { + var defaultProperty = Target.Type.GetScriptableDefaultProperty(this, invokeFlags, args, bindArgs); + if (defaultProperty != null) + { + return GetHostProperty(signature, defaultProperty, invokeFlags, args); + } + + if (Target.Type.IsArray && (Target.Type.GetArrayRank() == args.Length)) + { + // special case to enable VBScript "x(a, b, ...)" syntax when x is a multidimensional array + + var indices = new long[args.Length]; + var failed = false; + + for (var position = 0; position < args.Length; position++) + { + if (!MiscHelpers.TryGetNumericIndex(args[position], out long index)) + { + failed = true; + break; + } + + indices[position] = index; + } + + if (!failed) + { + return ((Array)Target.InvokeTarget).GetValue(indices); + } + } + + if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TryGetIndex(args, out var result)) + { + return result; + } + } + + return Nonexistent.Value; + } + + if (name == SpecialMemberNames.NewEnum) + { + return CreateScriptableEnumerator(); + } + + if (name == SpecialMemberNames.NewAsyncEnum) + { + return CreateAsyncEnumerator(); + } + + if ((TargetDynamicMetaObject != null) && (args.Length < 1)) + { + int index; + object result; + + if (TargetDynamicMetaObject.HasMember(name, invokeFlags.HasFlagNonAlloc(BindingFlags.IgnoreCase))) + { + if (TargetDynamicMetaObject.TryGetMember(name, out result)) + { + return result; + } + + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out index)) + { + if (TargetDynamicMetaObject.TryGetIndex(new object[] { index }, out result)) + { + return result; + } + } + + if (TargetDynamicMetaObject.TryGetIndex(new object[] { name }, out result)) + { + return result; + } + + if (includeBoundMembers) + { + if (HostMethodMap == null) + { + HostMethodMap = new Dictionary(MemberNameComparer); + } + + if (!HostMethodMap.TryGetValue(name, out var hostMethod)) + { + hostMethod = new HostMethod(this, name); + HostMethodMap.Add(name, hostMethod); + } + + return hostMethod; + } + + return Nonexistent.Value; + } + + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out index)) + { + if (TargetDynamicMetaObject.TryGetIndex(new object[] { index }, out result)) + { + return result; + } + } + + if (TargetDynamicMetaObject.TryGetIndex(new object[] { name }, out result)) + { + return result; + } + } + + var property = Target.Type.GetScriptableProperty(this, name, invokeFlags, args, bindArgs); + if (property != null) + { + return GetHostProperty(signature, property, invokeFlags, args); + } + + if (args.Length > 0) + { + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no suitable property named '{0}'", name)); + } + + var eventInfo = Target.Type.GetScriptableEvent(this, name, invokeFlags); + if (eventInfo != null) + { + isCacheable = (TargetDynamicMetaObject == null); + return typeof(EventSource<>).MakeSpecificType(eventInfo.EventHandlerType).CreateInstance(BindingFlags.NonPublic, Engine, Target.InvokeTarget, eventInfo); + } + + var field = Target.Type.GetScriptableField(this, name, invokeFlags); + if (field != null) + { + return GetHostField(signature, field, out isCacheable); + } + + if (includeBoundMembers) + { + if (Target.Type.GetScriptableProperties(this, name, invokeFlags).Any()) + { + if (HostIndexedPropertyMap == null) + { + HostIndexedPropertyMap = new Dictionary(); + } + + if (!HostIndexedPropertyMap.TryGetValue(name, out var hostIndexedProperty)) + { + hostIndexedProperty = new HostIndexedProperty(this, name); + HostIndexedPropertyMap.Add(name, hostIndexedProperty); + } + + return hostIndexedProperty; + } + + var method = ThisReflect.GetMethods(GetMethodBindFlags()).FirstOrDefault(testMethod => string.Equals(testMethod.Name, name, MemberNameComparison)); + if (method != null) + { + if (HostMethodMap == null) + { + HostMethodMap = new Dictionary(MemberNameComparer); + } + + if (!HostMethodMap.TryGetValue(name, out var hostMethod)) + { + hostMethod = new HostMethod(this, name); + HostMethodMap.Add(name, hostMethod); + } + + isCacheable = (TargetDynamicMetaObject == null); + return hostMethod; + } + } + + return Nonexistent.Value; + } + + private object GetHostProperty(BindSignature signature, PropertyInfo property, BindingFlags invokeFlags, object[] args) + { + if (reflectionProperties.Contains(property, MemberComparer.Instance)) + { + Engine.CheckReflection(); + } + + if ((property.GetIndexParameters().Length > 0) && (args.Length < 1) && !invokeFlags.HasFlag(BindingFlags.SuppressChangeType)) + { + if (HostIndexedPropertyMap == null) + { + HostIndexedPropertyMap = new Dictionary(); + } + + var name = property.Name; + if (!HostIndexedPropertyMap.TryGetValue(name, out var hostIndexedProperty)) + { + hostIndexedProperty = new HostIndexedProperty(this, name); + HostIndexedPropertyMap.Add(name, hostIndexedProperty); + } + + return hostIndexedProperty; + } + + var getMethod = property.GetMethod; + if ((getMethod == null) || !getMethod.IsAccessible(this) || getMethod.IsBlockedFromScript(this, property.GetScriptAccess(this, DefaultAccess), false)) + { + throw new UnauthorizedAccessException("The property get method is unavailable or inaccessible"); + } + + Engine.CachePropertyGetBindResult(signature, property); + return GetHostPropertyWorker(property, getMethod, args); + } + + private object GetHostPropertyWorker(PropertyInfo property, MethodInfo getMethod, object[] args) + { + return InvokeHelpers.InvokeMethod(this, getMethod, Target.InvokeTarget, args, property.GetScriptMemberFlags(this)); + } + + private object GetHostField(BindSignature signature, FieldInfo field, out bool isCacheable) + { + Engine.CachePropertyGetBindResult(signature, field); + return GetHostFieldWorker(field, out isCacheable); + } + + private object GetHostFieldWorker(FieldInfo field, out bool isCacheable) + { + var result = field.GetValue(Target.InvokeTarget); + isCacheable = (TargetDynamicMetaObject == null) && (field.IsLiteral || field.IsInitOnly); + return Engine.PrepareResult(result, field.FieldType, field.GetScriptMemberFlags(this), false); + } + + private object SetHostProperty(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs) + { + var signature = new BindSignature(AccessContext, invokeFlags, Target, name, ArrayHelpers.GetEmptyArray(), bindArgs); + if (Engine.TryGetCachedPropertySetBindResult(signature, out var boundMember)) + { + if (boundMember is PropertyInfo boundProperty) + { + return SetHostPropertyWorker(boundProperty, boundProperty.SetMethod, args, bindArgs); + } + + if (boundMember is FieldInfo boundField) + { + return SetHostFieldWorker(boundField, args); + } + } + + if (name == SpecialMemberNames.Default) + { + if (args.Length < 1) + { + throw new InvalidOperationException("Invalid argument count"); + } + + object result; + + var defaultProperty = Target.Type.GetScriptableDefaultProperty(this, invokeFlags, args.Take(args.Length - 1).ToArray(), bindArgs.Take(bindArgs.Length - 1).ToArray()); + if (defaultProperty != null) + { + return SetHostProperty(signature, defaultProperty, args, bindArgs); + } + + if (args.Length < 2) + { + throw new InvalidOperationException("Invalid argument count"); + } + + if (Target.Type.IsArray && (Target.Type.GetArrayRank() == (args.Length - 1))) + { + // special case to enable VBScript "x(a, b, ...) = value" syntax when x is a multidimensional array + + var indices = new long[args.Length - 1]; + var failed = false; + + for (var position = 0; position < (args.Length - 1); position++) + { + if (!MiscHelpers.TryGetNumericIndex(args[position], out long index)) + { + failed = true; + break; + } + + indices[position] = index; + } + + if (!failed) + { + var value = args[args.Length - 1]; + ((Array)Target.InvokeTarget).SetValue(value, indices); + return value; + } + } + + if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TrySetIndex(args.Take(args.Length - 1).ToArray(), args[args.Length - 1], out result)) + { + return result; + } + } + + // special case to enable JScript/VBScript "x(a) = b" syntax when x is a host indexed property + + if (InvokeHelpers.TryInvokeObject(this, Target, invokeFlags, args, bindArgs, false, out result)) + { + return result; + } + + throw new InvalidOperationException("Invalid property assignment"); + } + + if ((TargetDynamicMetaObject != null) && (args.Length == 1)) + { + if (TargetDynamicMetaObject.TrySetMember(name, args[0], out var result)) + { + return result; + } + + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + if (TargetDynamicMetaObject.TrySetIndex(new object[] { index }, args[0], out result)) + { + return result; + } + } + + if (TargetDynamicMetaObject.TrySetIndex(new object[] { name }, args[0], out result)) + { + return result; + } + } + + if (args.Length < 1) + { + throw new InvalidOperationException("Invalid argument count"); + } + + var property = Target.Type.GetScriptableProperty(this, name, invokeFlags, args.Take(args.Length - 1).ToArray(), bindArgs.Take(bindArgs.Length - 1).ToArray()); + if (property != null) + { + return SetHostProperty(signature, property, args, bindArgs); + } + + var field = Target.Type.GetScriptableField(this, name, invokeFlags); + if (field != null) + { + return SetHostField(signature, field, args); + } + + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no suitable property or field named '{0}'", name)); + } + + private object SetHostProperty(BindSignature signature, PropertyInfo property, object[] args, object[] bindArgs) + { + var scriptAccess = property.GetScriptAccess(this, DefaultAccess); + if (scriptAccess == ScriptAccess.ReadOnly) + { + throw new UnauthorizedAccessException("The property is read-only"); + } + + var setMethod = property.SetMethod; + if ((setMethod == null) || !setMethod.IsAccessible(this) || setMethod.IsBlockedFromScript(this, scriptAccess, false)) + { + throw new UnauthorizedAccessException("The property set method is unavailable or inaccessible"); + } + + Engine.CachePropertySetBindResult(signature, property); + return SetHostPropertyWorker(property, setMethod, args, bindArgs); + } + + private object SetHostPropertyWorker(PropertyInfo property, MethodInfo setMethod, object[] args, object[] bindArgs) + { + var value = args[args.Length - 1]; + + var argCount = args.Length - 1; + var paramCount = property.GetIndexParameters().Length; + if (argCount < paramCount) + { + var missingArgs = Enumerable.Repeat(Missing.Value, paramCount - argCount).ToArray(); + args = args.Take(argCount).Concat(missingArgs).Concat(value.ToEnumerable()).ToArray(); + bindArgs = bindArgs.Take(argCount).Concat(missingArgs).Concat(bindArgs[bindArgs.Length - 1].ToEnumerable()).ToArray(); + } + + // ReSharper disable once SuspiciousTypeConversion.Global + if ((value != null) && (Engine is IVBScriptEngineTag)) + { + // special case to emulate VBScript's default property handling + + if (value is IWindowsScriptItemTag) + { + var defaultValue = ((IDynamic)value).GetProperty(SpecialMemberNames.Default); + if (!(defaultValue is Undefined)) + { + value = defaultValue; + } + } + else + { + if (Wrap(Engine, bindArgs[bindArgs.Length - 1]) is HostItem hostItem) + { + if (MiscHelpers.Try(out var defaultValue, () => ((IDynamic)hostItem).GetProperty(SpecialMemberNames.Default)) && (defaultValue != null)) + { + value = defaultValue; + } + } + } + } + + if (property.PropertyType.IsAssignableFromValue(ref value)) + { + args[args.Length - 1] = value; + InvokeHelpers.InvokeMethod(this, setMethod, Target.InvokeTarget, args, property.GetScriptMemberFlags(this)); + return value; + } + + // Some COM properties have setters where the final parameter type doesn't match + // the property type. The latter has failed, so let's try the former. + + var setParams = setMethod.GetParameters(); + if ((setParams.Length >= args.Length) && (setParams[args.Length - 1].ParameterType.IsAssignableFromValue(ref value))) + { + args[args.Length - 1] = value; + InvokeHelpers.InvokeMethod(this, setMethod, Target.InvokeTarget, args, property.GetScriptMemberFlags(this)); + return value; + } + + throw new ArgumentException("Invalid property assignment"); + } + + private object SetHostField(BindSignature signature, FieldInfo field, object[] args) + { + if (args.Length != 1) + { + throw new InvalidOperationException("Invalid argument count"); + } + + if (field.IsLiteral || field.IsInitOnly || field.IsReadOnlyForScript(this, DefaultAccess)) + { + throw new UnauthorizedAccessException("The field is read-only"); + } + + Engine.CachePropertySetBindResult(signature, field); + return SetHostFieldWorker(field, args); + } + + private object SetHostFieldWorker(FieldInfo field, object[] args) + { + var value = args[0]; + if (field.FieldType.IsAssignableFromValue(ref value)) + { + field.SetValue(Target.InvokeTarget, value); + return value; + } + + throw new ArgumentException("Invalid field assignment"); + } + + private static object CreateScriptableEnumerator(IEnumerable enumerable) + { + return HostObject.Wrap(new ScriptableEnumeratorOnEnumerator(enumerable.GetEnumerator()), typeof(IScriptableEnumerator)); + } + + private object CreateScriptableEnumerator() + { + if ((Target is HostObject) || (Target is IHostVariable) || (Target is IByRefArg)) + { + if (Target.InvokeTarget is IScriptableEnumerator scriptableEnumerator) + return scriptableEnumerator; + + if ((Target.InvokeTarget != null) && Target.Type.IsAssignableToGenericType(typeof(IEnumerable<>), out var typeArgs)) + { + var helpersHostItem = Wrap(Engine, typeof(ScriptableEnumerableHelpers<>).MakeGenericType(typeArgs).InvokeMember("HostType", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField, null, null, null), HostItemFlags.PrivateAccess); + if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableEnumerator", this))) + { + return enumerator; + } + } + else if (BindSpecialTarget(out IEnumerable _)) + { + var helpersHostItem = Wrap(Engine, ScriptableEnumerableHelpers.HostType, HostItemFlags.PrivateAccess); + if (MiscHelpers.Try(out var enumerator, () => ((IDynamic)helpersHostItem).InvokeMethod("GetScriptableEnumerator", this))) + { + return enumerator; + } + } + } + + throw new NotSupportedException("The object is not enumerable"); + } + + #endregion + + #endregion + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("[{0}]", Target); + } + + #endregion + + #region DynamicObject overrides + + public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result) + { + result = ThisDynamic.Invoke(true, args).ToDynamicResult(Engine); + return true; + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + result = ThisDynamic.GetProperty(binder.Name).ToDynamicResult(Engine); + return true; + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + ThisDynamic.SetProperty(binder.Name, value); + return true; + } + + public override bool TryGetIndex(GetIndexBinder binder, object[] indices, out object result) + { + if (indices.Length == 1) + { + if (MiscHelpers.TryGetNumericIndex(indices[0], out int index)) + { + result = ThisDynamic.GetProperty(index).ToDynamicResult(Engine); + return true; + } + + result = ThisDynamic.GetProperty(indices[0].ToString()).ToDynamicResult(Engine); + return true; + } + + if (indices.Length > 1) + { + result = ThisDynamic.GetProperty(SpecialMemberNames.Default, indices).ToDynamicResult(Engine); + return true; + } + + throw new InvalidOperationException("Invalid argument or index count"); + } + + public override bool TrySetIndex(SetIndexBinder binder, object[] indices, object value) + { + if (indices.Length == 1) + { + if (MiscHelpers.TryGetNumericIndex(indices[0], out int index)) + { + ThisDynamic.SetProperty(index, value); + return true; + } + + ThisDynamic.SetProperty(indices[0].ToString(), value); + return true; + } + + if (indices.Length > 1) + { + ThisDynamic.SetProperty(SpecialMemberNames.Default, indices.Concat(value.ToEnumerable()).ToArray()); + } + + throw new InvalidOperationException("Invalid argument or index count"); + } + + public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) + { + result = ThisDynamic.Invoke(false, args).ToDynamicResult(Engine); + return true; + } + + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + result = ThisDynamic.InvokeMethod(binder.Name, args).ToDynamicResult(Engine); + return true; + } + + public override bool TryConvert(ConvertBinder binder, out object result) + { + if ((Target is HostObject) || (Target is IHostVariable) || (Target is IByRefArg)) + { + if (binder.Type.IsAssignableFrom(Target.Type)) + { + result = Convert.ChangeType(Target.InvokeTarget, binder.Type); + return true; + } + } + + result = null; + return false; + } + + #endregion + + #region IReflect implementation + + FieldInfo IReflect.GetField(string name, BindingFlags bindFlags) + { + var fields = ThisReflect.GetFields(bindFlags).Where(field => string.Equals(field.Name, name, bindFlags.GetMemberNameComparison())).ToArray(); + if (fields.Length < 1) + { + return null; + } + + if (fields.Length > 1) + { + throw new AmbiguousMatchException(MiscHelpers.FormatInvariant("The object has multiple fields named '{0}'", name)); + } + + return fields[0]; + } + + FieldInfo[] IReflect.GetFields(BindingFlags bindFlags) + { + return HostInvoke(() => + { + UpdateFieldNames(out var updated); + if (updated || (AllFields == null)) + { + AllFields = MemberMap.GetFields(AllFieldNames); + } + + return AllFields; + }); + } + + MemberInfo[] IReflect.GetMember(string name, BindingFlags bindFlags) + { + return ThisReflect.GetMembers(bindFlags).Where(member => string.Equals(member.Name, name, bindFlags.GetMemberNameComparison())).ToArray(); + } + + MemberInfo[] IReflect.GetMembers(BindingFlags bindFlags) + { + return ThisReflect.GetFields(bindFlags).Cast().Concat(ThisReflect.GetMethods(bindFlags)).Concat(ThisReflect.GetProperties(bindFlags)).ToArray(); + } + + MethodInfo IReflect.GetMethod(string name, BindingFlags bindFlags) + { + var methods = ThisReflect.GetMethods(bindFlags).Where(method => string.Equals(method.Name, name, bindFlags.GetMemberNameComparison())).ToArray(); + if (methods.Length < 1) + { + return null; + } + + if (methods.Length > 1) + { + throw new AmbiguousMatchException(MiscHelpers.FormatInvariant("The object has multiple methods named '{0}'", name)); + } + + return methods[0]; + } + + MethodInfo IReflect.GetMethod(string name, BindingFlags bindFlags, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + MethodInfo[] IReflect.GetMethods(BindingFlags bindFlags) + { + return HostInvoke(() => + { + UpdateMethodNames(out var updated); + if (updated || (AllMethods == null)) + { + AllMethods = MemberMap.GetMethods(AllMethodNames); + } + + return AllMethods; + }); + } + + PropertyInfo[] IReflect.GetProperties(BindingFlags bindFlags) + { + return HostInvoke(() => + { + UpdatePropertyNames(out var updated); + if (updated || (AllProperties == null)) + { + AllProperties = MemberMap.GetProperties(AllPropertyNames); + } + + return AllProperties; + }); + } + + PropertyInfo IReflect.GetProperty(string name, BindingFlags bindFlags, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + PropertyInfo IReflect.GetProperty(string name, BindingFlags bindFlags) + { + var properties = ThisReflect.GetProperties(bindFlags).Where(property => string.Equals(property.Name, name, bindFlags.GetMemberNameComparison())).ToArray(); + if (properties.Length < 1) + { + return null; + } + + if (properties.Length > 1) + { + throw new AmbiguousMatchException(MiscHelpers.FormatInvariant("The object has multiple properties named '{0}'", name)); + } + + return properties[0]; + } + + object IReflect.InvokeMember(string name, BindingFlags invokeFlags, Binder binder, object invokeTarget, object[] wrappedArgs, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParams) + { + return InvokeReflectMember(name, invokeFlags, wrappedArgs, culture, namedParams); + } + + Type IReflect.UnderlyingSystemType => throw new NotImplementedException(); + + #endregion + + #region IDynamic implementation + + object IDynamic.GetProperty(string name, params object[] args) + { + return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null); + } + + object IDynamic.GetProperty(string name, out bool isCacheable, params object[] args) + { + return InvokeReflectMember(name, BindingFlags.GetProperty, args, CultureInfo.InvariantCulture, null, out isCacheable); + } + + void IDynamic.SetProperty(string name, object[] args) + { + ThisReflect.InvokeMember(name, BindingFlags.SetProperty, null, ThisReflect, args, null, CultureInfo.InvariantCulture, null); + } + + bool IDynamic.DeleteProperty(string name) + { + return HostInvoke(() => + { + if (TargetDynamic != null) + { + return TargetDynamic.DeleteProperty(name); + } + + if (TargetPropertyBag != null) + { + return TargetPropertyBag.Remove(name); + } + + if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TryDeleteMember(name, out var result) && result) + { + return true; + } + + if (TargetDynamicMetaObject.TryDeleteIndex(new object[] { name }, out result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic member deletion"); + } + + throw new NotSupportedException("The object does not support dynamic members"); + }); + } + + string[] IDynamic.GetPropertyNames() + { + return HostInvoke(() => + { + UpdateFieldNames(out var updatedFieldNames); + UpdateMethodNames(out var updatedMethodNames); + UpdatePropertyNames(out var updatedPropertyNames); + UpdateEnumerationSettingsToken(out var updatedEnumerationSettingsToken); + + if (updatedFieldNames || updatedMethodNames || updatedPropertyNames || updatedEnumerationSettingsToken || (AllMemberNames == null)) + { + AllMemberNames = AllFieldNames.Concat(EnumeratedMethodNames).Concat(AllPropertyNames).ExcludeIndices().Distinct().ToArray(); + } + + return AllMemberNames; + }); + } + + object IDynamic.GetProperty(int index) + { + return ThisDynamic.GetProperty(index.ToString(CultureInfo.InvariantCulture)); + } + + void IDynamic.SetProperty(int index, object value) + { + ThisDynamic.SetProperty(index.ToString(CultureInfo.InvariantCulture), value); + } + + bool IDynamic.DeleteProperty(int index) + { + return HostInvoke(() => + { + if (TargetDynamic != null) + { + return TargetDynamic.DeleteProperty(index); + } + + if (TargetPropertyBag != null) + { + return TargetPropertyBag.Remove(index.ToString(CultureInfo.InvariantCulture)); + } + + if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TryDeleteMember(index.ToString(CultureInfo.InvariantCulture), out var result) && result) + { + return true; + } + + if (TargetDynamicMetaObject.TryDeleteIndex(new object[] { index }, out result)) + { + return result; + } + + throw new InvalidOperationException("Invalid dynamic member deletion"); + } + + return false; + }); + } + + int[] IDynamic.GetPropertyIndices() + { + return HostInvoke(() => + { + UpdatePropertyNames(out var updated); + if (updated || (PropertyIndices == null)) + { + PropertyIndices = AllPropertyNames.GetIndices().Distinct().ToArray(); + } + + return PropertyIndices; + }); + } + + object IDynamic.Invoke(bool asConstructor, params object[] args) + { + return ThisReflect.InvokeMember(SpecialMemberNames.Default, asConstructor ? BindingFlags.CreateInstance : ((args.Length < 1) ? BindingFlags.InvokeMethod : BindingFlags.InvokeMethod | BindingFlags.GetProperty), null, ThisReflect, args, null, CultureInfo.InvariantCulture, null); + } + + object IDynamic.InvokeMethod(string name, params object[] args) + { + return ThisReflect.InvokeMember(name, BindingFlags.InvokeMethod, null, ThisReflect, args, null, CultureInfo.InvariantCulture, null); + } + + #endregion + + #region IEnumVARIANT implementation + + int IEnumVARIANT.Next(int count, object[] elements, IntPtr pCountFetched) + { + return HostInvoke(() => + { + var index = 0; + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (elements != null) + { + var maxCount = Math.Min(count, elements.Length); + if (index < maxCount) + { + var currentName = (TargetEnumerator is IScriptableEnumerator) ? "ScriptableCurrent" : "Current"; + while ((index < maxCount) && TargetEnumerator.MoveNext()) + { + elements[index++] = ThisDynamic.GetProperty(currentName); + } + } + } + + if (pCountFetched != IntPtr.Zero) + { + Marshal.WriteInt32(pCountFetched, index); + } + + return (index == count) ? HResult.S_OK : HResult.S_FALSE; + }); + } + + int IEnumVARIANT.Skip(int count) + { + return HostInvoke(() => + { + var index = 0; + while ((index < count) && TargetEnumerator.MoveNext()) + { + index++; + } + + return (index == count) ? HResult.S_OK : HResult.S_FALSE; + }); + } + + int IEnumVARIANT.Reset() + { + return HostInvoke(() => + { + TargetEnumerator.Reset(); + return HResult.S_OK; + }); + } + + IEnumVARIANT IEnumVARIANT.Clone() + { + throw new NotImplementedException(); + } + + #endregion + + #region ICustomQueryInterface implementation + + public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr pInterface) + { + if (!MiscHelpers.PlatformIsWindows()) + { + pInterface = IntPtr.Zero; + return CustomQueryInterfaceResult.NotHandled; + } + + if (iid == typeof(IEnumVARIANT).GUID) + { + if ((Target is HostObject) || (Target is IHostVariable) || (Target is IByRefArg)) + { + pInterface = IntPtr.Zero; + return BindSpecialTarget(Collateral.TargetEnumerator) ? CustomQueryInterfaceResult.NotHandled : CustomQueryInterfaceResult.Failed; + } + } + else if (iid == typeof(IDispatchEx).GUID) + { + if (EnableVTablePatching && !bypassVTablePatching) + { + var pUnknown = Marshal.GetIUnknownForObject(this); + + bypassVTablePatching = true; + pInterface = UnknownHelpers.QueryInterfaceNoThrow(pUnknown); + bypassVTablePatching = false; + + Marshal.Release(pUnknown); + + if (pInterface != IntPtr.Zero) + { + VTablePatcher.GetInstance().PatchDispatchEx(pInterface); + return CustomQueryInterfaceResult.Handled; + } + } + } + + pInterface = IntPtr.Zero; + return CustomQueryInterfaceResult.NotHandled; + } + + #endregion + + #region IScriptMarshalWrapper implementation + + public ScriptEngine Engine { get; } + + public object Unwrap() + { + return Target.Target; + } + + #endregion + + #region IHostTargetContext implementation + + public CustomAttributeLoader CustomAttributeLoader => CachedCustomAttributeLoader; + + public Type AccessContext => CachedAccessContext; + + public ScriptAccess DefaultAccess => CachedDefaultAccess; + + public HostTargetFlags TargetFlags => CachedTargetFlags; + + #endregion + + #region Nested type: ExpandoHostItem + + private class ExpandoHostItem : HostItem, IExpando + { + #region constructors + + // ReSharper disable MemberCanBeProtected.Local + + public ExpandoHostItem(ScriptEngine engine, HostTarget target, HostItemFlags flags) + : base(engine, target, flags) + { + } + + // ReSharper restore MemberCanBeProtected.Local + + #endregion + + #region IExpando implementation + + FieldInfo IExpando.AddField(string name) + { + return HostInvoke(() => + { + if (CanAddExpandoMembers()) + { + AddExpandoMemberName(name); + return MemberMap.GetField(name); + } + + throw new NotSupportedException("The object does not support dynamic fields"); + }); + } + + PropertyInfo IExpando.AddProperty(string name) + { + return HostInvoke(() => + { + if (CanAddExpandoMembers()) + { + AddExpandoMemberName(name); + return MemberMap.GetProperty(name); + } + + throw new NotSupportedException("The object does not support dynamic properties"); + }); + } + + MethodInfo IExpando.AddMethod(string name, Delegate method) + { + throw new NotImplementedException(); + } + + void IExpando.RemoveMember(MemberInfo member) + { + RemoveMember(member.Name); + } + + protected virtual bool RemoveMember(string name) + { + return HostInvoke(() => + { + if (TargetDynamic != null) + { + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + if (TargetDynamic.DeleteProperty(index)) + { + RemoveExpandoMemberName(index.ToString(CultureInfo.InvariantCulture)); + return true; + } + } + else if (TargetDynamic.DeleteProperty(name)) + { + RemoveExpandoMemberName(name); + return true; + } + } + else if (TargetPropertyBag != null) + { + if (TargetPropertyBag.Remove(name)) + { + RemoveExpandoMemberName(name); + return true; + } + } + else if (TargetDynamicMetaObject != null) + { + if (TargetDynamicMetaObject.TryDeleteMember(name, out var result) && result) + { + RemoveExpandoMemberName(name); + return true; + } + + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index) && TargetDynamicMetaObject.TryDeleteIndex(new object[] { index }, out result)) + { + RemoveExpandoMemberName(index.ToString(CultureInfo.InvariantCulture)); + return true; + } + + if (TargetDynamicMetaObject.TryDeleteIndex(new object[] { name }, out result)) + { + RemoveExpandoMemberName(name); + return true; + } + } + else + { + throw new NotSupportedException("The object does not support dynamic members"); + } + + return false; + }); + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostItem.cs.meta b/Unity/Package/Runtime/HostItem.cs.meta new file mode 100644 index 000000000..6de3cfaaf --- /dev/null +++ b/Unity/Package/Runtime/HostItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3758084d8ba5f7e4f902c5b43273d243 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostItemCollateral.cs b/Unity/Package/Runtime/HostItemCollateral.cs new file mode 100644 index 000000000..a97d8cbf0 --- /dev/null +++ b/Unity/Package/Runtime/HostItemCollateral.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections; +using System.Collections.Generic; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class HostItemCollateral + { + #region special targets + + public readonly CollateralObject TargetDynamic = new CollateralObject(); + public readonly CollateralObject TargetPropertyBag = new CollateralObject(); + public readonly CollateralObject TargetList = new CollateralObject(); + public readonly CollateralObject TargetDynamicMetaObject = new CollateralObject(); + public readonly CollateralObject TargetEnumerator = new CollateralObject(); + + #endregion + + #region dynamic collateral + + public readonly CollateralObject> ExpandoMemberNames = new CollateralObject>(); + public readonly CollateralObject ListData = new CollateralObject(); + + #endregion + + #region tear-off member cache + + public readonly CollateralObject> HostMethodMap = new CollateralObject>(); + public readonly CollateralObject> HostIndexedPropertyMap = new CollateralObject>(); + + #endregion + + #region Nested type: CollateralObject + + public class CollateralObject : CollateralObject where T : class + { + } + + #endregion + + #region Nested type: ListDataFields + + public class ListDataFields + { + public int[] PropertyIndices; + public int CachedCount; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostItemCollateral.cs.meta b/Unity/Package/Runtime/HostItemCollateral.cs.meta new file mode 100644 index 000000000..3a69e472c --- /dev/null +++ b/Unity/Package/Runtime/HostItemCollateral.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50178c1522bd8a3438f1f667824eb1fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostItemFlags.cs b/Unity/Package/Runtime/HostItemFlags.cs new file mode 100644 index 000000000..b6e0fcc89 --- /dev/null +++ b/Unity/Package/Runtime/HostItemFlags.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Dynamic; + +namespace Microsoft.ClearScript +{ + /// + /// Defines options for exposing host resources to script code. + /// + [Flags] + public enum HostItemFlags + { + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that the host resource's members are to be exposed as global items in the + /// script engine's root namespace. + /// + GlobalMembers = 0x00000001, + + /// + /// Specifies that the host resource's non-public members are to be exposed. + /// + PrivateAccess = 0x00000002, + + /// + /// Specifies that the host resource's dynamic members are not to be exposed. This option + /// applies only to objects that implement . + /// + HideDynamicMembers = 0x00000004, + + /// + /// Specifies that the script engine is to be given direct access to the exposed object if + /// possible. This option, when supported, suppresses marshaling and hands off the object + /// for script access without the host's involvement. It is currently supported only for + /// COM and COM-visible + /// objects exposed in Windows Script engines. + /// + DirectAccess = 0x00000008 + } +} diff --git a/Unity/Package/Runtime/HostItemFlags.cs.meta b/Unity/Package/Runtime/HostItemFlags.cs.meta new file mode 100644 index 000000000..636de9c9f --- /dev/null +++ b/Unity/Package/Runtime/HostItemFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7adccdceb9f4b248bfb6374f7bccf9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostList.cs b/Unity/Package/Runtime/HostList.cs new file mode 100644 index 000000000..3d7b448f5 --- /dev/null +++ b/Unity/Package/Runtime/HostList.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal interface IHostList + { + int Count { get; } + object this[int index] { get; set; } + } + + internal sealed class HostList : IHostList + { + private readonly ScriptEngine engine; + private readonly IList list; + private readonly Type elementType; + + public HostList(ScriptEngine engine, IList list, Type elementType) + { + this.engine = engine; + this.list = list; + this.elementType = elementType; + } + + #region IHostList implementation + + public int Count => list.Count; + + public object this[int index] + { + get => engine.PrepareResult(list[index], elementType, ScriptMemberFlags.None, true); + set => list[index] = value; + } + + #endregion + } + + internal sealed class HostList : IHostList + { + private readonly ScriptEngine engine; + private readonly IList list; + + public HostList(ScriptEngine engine, IList list) + { + this.engine = engine; + this.list = list; + } + + #region IHostList implementation + + public int Count => list.Count; + + public object this[int index] + { + get => engine.PrepareResult(list[index], ScriptMemberFlags.None, true); + + set + { + if (!typeof(T).IsAssignableFromValue(ref value)) + { + throw new InvalidOperationException("Assignment invalid due to type mismatch"); + } + + list[index] = (T)value; + } + } + + #endregion + } + + internal sealed class ReadOnlyHostList : IHostList + { + private readonly ScriptEngine engine; + private readonly IReadOnlyList list; + + public ReadOnlyHostList(ScriptEngine engine, IReadOnlyList list) + { + this.engine = engine; + this.list = list; + } + + #region IHostList implementation + + public int Count => list.Count; + + public object this[int index] + { + get => engine.PrepareResult(list[index], ScriptMemberFlags.None, true); + + set => throw new UnauthorizedAccessException("The object is read-only"); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostList.cs.meta b/Unity/Package/Runtime/HostList.cs.meta new file mode 100644 index 000000000..752fdc7a1 --- /dev/null +++ b/Unity/Package/Runtime/HostList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07047fe212cc64346a440485ac52d9c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostMethod.cs b/Unity/Package/Runtime/HostMethod.cs new file mode 100644 index 000000000..0c2703250 --- /dev/null +++ b/Unity/Package/Runtime/HostMethod.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class HostMethod : HostTarget + { + private readonly HostItem target; + private readonly string name; + + public HostMethod(HostItem target, string name) + { + this.target = target; + this.name = name; + } + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("HostMethod:{0}", name); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => typeof(void); + + public override object Target => this; + + public override object InvokeTarget => null; + + public override object DynamicInvokeTarget => null; + + public override HostTargetFlags GetFlags(IHostContext context) + { + return HostTargetFlags.None; + } + + public override bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + result = target.InvokeMember(name, invokeFlags, args, bindArgs, null, true); + return true; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return Invocability.Delegate; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostMethod.cs.meta b/Unity/Package/Runtime/HostMethod.cs.meta new file mode 100644 index 000000000..4c30a8e72 --- /dev/null +++ b/Unity/Package/Runtime/HostMethod.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8100e19bad52434eac3642cb72eb5d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostObject.cs b/Unity/Package/Runtime/HostObject.cs new file mode 100644 index 000000000..fea3d6ce0 --- /dev/null +++ b/Unity/Package/Runtime/HostObject.cs @@ -0,0 +1,159 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class HostObject : HostTarget + { + #region data + + private readonly object target; + private readonly Type type; + private static readonly MethodInfo getNullWrapperGenericMethod = typeof(HostObject).GetMethod("GetNullWrapperGeneric", BindingFlags.NonPublic | BindingFlags.Static); + + #endregion + + #region constructors + + private HostObject(object target, Type type) + { + target = CanonicalRefTable.GetCanonicalRef(target); + if (type == null) + { + type = target.GetType(); + } + + if (type.IsUnknownCOMObject()) + { + if (target is IEnumVARIANT enumVariant) + { + target = new ScriptableEnumeratorOnEnumVariant(enumVariant); + type = typeof(IScriptableEnumerator); + } + } + + this.target = target; + this.type = type; + } + + #endregion + + #region wrappers + + public static HostObject Wrap(object target) + { + return Wrap(target, null); + } + + public static HostObject Wrap(object target, Type type) + { + return (target != null) ? new HostObject(target, type) : null; + } + + public static object WrapResult(object result, Type type, bool wrapNull) + { + if ((result is HostItem) || (result is HostTarget)) + { + return result; + } + + if (result == null) + { + return wrapNull ? GetNullWrapper(type) : null; + } + + if ((type == typeof(void)) || (type == typeof(object)) || type.IsNullable()) + { + return result; + } + + if ((type == result.GetType()) || (Type.GetTypeCode(type) != TypeCode.Object)) + { + return result; + } + + return Wrap(result, type); + } + + #endregion + + #region internal members + + private static HostObject GetNullWrapper(Type type) + { + return (HostObject)getNullWrapperGenericMethod.MakeGenericMethod(type).Invoke(null, ArrayHelpers.GetEmptyArray()); + } + + // ReSharper disable UnusedMember.Local + + private static HostObject GetNullWrapperGeneric() + { + return NullWrapper.Value; + } + + // ReSharper restore UnusedMember.Local + + #endregion + + #region Object overrides + + public override string ToString() + { + if ((target is ScriptItem) && (typeof(ScriptItem).IsAssignableFrom(type))) + { + return "ScriptItem"; + } + + var objectName = target.GetFriendlyName(type); + return MiscHelpers.FormatInvariant("HostObject:{0}", objectName); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => type; + + public override object Target => target; + + public override object InvokeTarget => target; + + public override object DynamicInvokeTarget => target; + + public override HostTargetFlags GetFlags(IHostContext context) + { + var flags = HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods; + if (context.Engine.ExposeHostObjectStaticMembers) + { + flags |= HostTargetFlags.AllowStaticMembers; + } + + return flags; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return type.GetInvocability(context, bindFlags, ignoreDynamic); + } + + #endregion + + #region Nested type: NullWrapper + + // ReSharper disable UnusedMember.Local + + private static class NullWrapper + { + public static readonly HostObject Value = new HostObject(null, typeof(T)); + } + + // ReSharper restore UnusedMember.Local + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostObject.cs.meta b/Unity/Package/Runtime/HostObject.cs.meta new file mode 100644 index 000000000..e282183b6 --- /dev/null +++ b/Unity/Package/Runtime/HostObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 000f84b714d0d4044b489d303b38c923 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostSettings.cs b/Unity/Package/Runtime/HostSettings.cs new file mode 100644 index 000000000..57596d9e0 --- /dev/null +++ b/Unity/Package/Runtime/HostSettings.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Defines properties that comprise ClearScript's global configuration. + /// + public static class HostSettings + { + private static CustomAttributeLoader customAttributeLoader; + + /// + /// Enables or disables assembly table usage. + /// + /// + /// + /// The assembly table is a legacy internal feature intended to accelerate assembly + /// loading. Because it relies on deprecated platform functionality, this feature is now + /// disabled by default. Although its replacement is simpler and more efficient, the + /// feature is still available to provide full compatibility with older ClearScript + /// releases. + /// + /// + /// The assembly table feature is only available on .NET Framework. This property has no + /// effect on other platforms. + /// + /// + public static bool UseAssemblyTable { get; set; } + + /// + /// Gets or sets a semicolon-delimited list of directory paths to search for auxiliary files. + /// + /// + /// This property allows the host to augment ClearScript's algorithm for locating unmanaged + /// resources such as native assemblies and related data files. + /// + public static string AuxiliarySearchPath { get; set; } + + /// + /// Gets or sets the custom attribute loader for ClearScript. + /// + /// + /// When not explicitly assigned to a non-null value, this property returns the + /// default custom attribute loader. + /// + public static CustomAttributeLoader CustomAttributeLoader + { + get => customAttributeLoader ?? CustomAttributeLoader.Default; + set => customAttributeLoader = value; + } + } +} diff --git a/Unity/Package/Runtime/HostSettings.cs.meta b/Unity/Package/Runtime/HostSettings.cs.meta new file mode 100644 index 000000000..037b26490 --- /dev/null +++ b/Unity/Package/Runtime/HostSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fb36421bab2bac4a9c8e1ac8a1bb819 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostTarget.cs b/Unity/Package/Runtime/HostTarget.cs new file mode 100644 index 000000000..c295ddfde --- /dev/null +++ b/Unity/Package/Runtime/HostTarget.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal abstract class HostTarget + { + public abstract Type Type { get; } + + public abstract object Target { get; } + + public abstract object InvokeTarget { get; } + + public abstract object DynamicInvokeTarget { get; } + + public abstract HostTargetFlags GetFlags(IHostContext context); + + public virtual string[] GetAuxMethodNames(IHostContext context, BindingFlags bindFlags) + { + return ArrayHelpers.GetEmptyArray(); + } + + public virtual string[] GetAuxPropertyNames(IHostContext context, BindingFlags bindFlags) + { + return ArrayHelpers.GetEmptyArray(); + } + + public virtual bool TryInvokeAuxMember(IHostContext context, string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + result = null; + return false; + } + + public virtual bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + result = null; + return false; + } + + public abstract Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic); + } +} diff --git a/Unity/Package/Runtime/HostTarget.cs.meta b/Unity/Package/Runtime/HostTarget.cs.meta new file mode 100644 index 000000000..ab491662f --- /dev/null +++ b/Unity/Package/Runtime/HostTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afe15a04ccf5a06428c054b8e3e39bda +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostTargetFlags.cs b/Unity/Package/Runtime/HostTargetFlags.cs new file mode 100644 index 000000000..baa321121 --- /dev/null +++ b/Unity/Package/Runtime/HostTargetFlags.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + [Flags] + internal enum HostTargetFlags + { + None = 0, + AllowStaticMembers = 0x00000001, + AllowInstanceMembers = 0x00000002, + AllowExtensionMethods = 0x00000004 + } +} diff --git a/Unity/Package/Runtime/HostTargetFlags.cs.meta b/Unity/Package/Runtime/HostTargetFlags.cs.meta new file mode 100644 index 000000000..fe1c1ba44 --- /dev/null +++ b/Unity/Package/Runtime/HostTargetFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91f66434690a2d146a1ff1dd425d257d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostTargetMemberData.cs b/Unity/Package/Runtime/HostTargetMemberData.cs new file mode 100644 index 000000000..23383e7b5 --- /dev/null +++ b/Unity/Package/Runtime/HostTargetMemberData.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; + +namespace Microsoft.ClearScript +{ + internal class HostTargetMemberData + { + public string[] TypeEventNames; + public string[] TypeFieldNames; + public string[] TypeMethodNames; + public string[] TypePropertyNames; + + public string[] AllFieldNames; + public string[] AllMethodNames; + public string[] OwnMethodNames; + public string[] AllPropertyNames; + public string[] AllMemberNames; + + public FieldInfo[] AllFields; + public MethodInfo[] AllMethods; + public PropertyInfo[] AllProperties; + + public object EnumerationSettingsToken; + public ExtensionMethodSummary ExtensionMethodSummary; + public Invocability? TargetInvocability; + } + + internal class HostTargetMemberDataWithContext : HostTargetMemberData + { + public readonly CustomAttributeLoader CustomAttributeLoader; + public readonly Type AccessContext; + public readonly ScriptAccess DefaultAccess; + public readonly HostTargetFlags TargetFlags; + + public HostTargetMemberDataWithContext(CustomAttributeLoader customAttributeLoader, Type accessContext, ScriptAccess defaultAccess, HostTargetFlags targetFlags) + { + CustomAttributeLoader = customAttributeLoader; + AccessContext = accessContext; + DefaultAccess = defaultAccess; + TargetFlags = targetFlags; + } + } +} diff --git a/Unity/Package/Runtime/HostTargetMemberData.cs.meta b/Unity/Package/Runtime/HostTargetMemberData.cs.meta new file mode 100644 index 000000000..b51eaa3f4 --- /dev/null +++ b/Unity/Package/Runtime/HostTargetMemberData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 98fef43587f571949b8a47869612b796 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostType.cs b/Unity/Package/Runtime/HostType.cs new file mode 100644 index 000000000..7de99ebdc --- /dev/null +++ b/Unity/Package/Runtime/HostType.cs @@ -0,0 +1,242 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class HostType : HostTarget, IScriptableObject + { + private HostType(Type type) + : this(new[] { type }) + { + } + + private HostType(Type[] types) + { + Debug.Assert((types != null) && (types.Length > 0)); + + var nestingGroups = types.GroupBy(type => type.IsNested).ToIList(); + if (nestingGroups.Count != 1) + { + throw new NotSupportedException("Cannot create type wrapper for multiple unrelated types"); + } + + var nested = nestingGroups[0].Key; + if (nested) + { + if (types.GroupBy(type => type.DeclaringType).Count() > 1) + { + throw new NotSupportedException("Cannot create type wrapper for multiple unrelated types"); + } + } + else + { + if (types.GroupBy(type => type.GetLocator()).Count() > 1) + { + throw new NotSupportedException("Cannot create type wrapper for multiple unrelated types"); + } + } + + var specificTypes = types.Where(testType => testType.IsSpecific()); + if (specificTypes.Count() > 1) + { + throw new NotSupportedException("Cannot create type wrapper for multiple specific types"); + } + + Types = types; + } + + public static HostType Wrap(Type type) + { + return (type != null) ? new HostType(type) : null; + } + + public static HostType Wrap(Type[] types) + { + return ((types != null) && (types.Length > 0)) ? new HostType(types) : null; + } + + public Type[] Types { get; } + + public Type GetSpecificType() + { + var type = GetSpecificTypeNoThrow(); + if (type == null) + { + throw new InvalidOperationException(MiscHelpers.FormatInvariant("'{0}' requires type arguments", Types[0].GetRootName())); + } + + return type; + } + + public Type GetTypeArg() + { + var type = GetSpecificType(); + + if (type.IsStatic()) + { + throw new InvalidOperationException(MiscHelpers.FormatInvariant("'{0}': static types cannot be used as type arguments", type.GetRootName())); + } + + if (type.IsUnknownCOMObject()) + { + throw new InvalidOperationException("Unknown COM/ActiveX types cannot be used as type arguments"); + } + + return type; + } + + public Type GetTypeArgNoThrow() + { + var type = GetSpecificTypeNoThrow(); + return ((type == null) || type.IsStatic() || type.IsUnknownCOMObject()) ? null : type; + } + + private Type GetSpecificTypeNoThrow() + { + return Types.FirstOrDefault(testType => testType.IsSpecific()); + } + + #region Object overrides + + public override string ToString() + { + var type = GetSpecificTypeNoThrow(); + if (type != null) + { + return MiscHelpers.FormatInvariant("HostType:{0}", type.GetFriendlyName()); + } + + var typeArgs = Types[0].GetGenericArguments(); + var parentPrefix = string.Empty; + if (Types[0].IsNested) + { + var parentType = Types[0].DeclaringType.MakeSpecificType(typeArgs); + parentPrefix = parentType.GetFriendlyName() + "."; + } + + return MiscHelpers.FormatInvariant((Types.Length > 1) ? "HostTypeGroup:{0}{1}" : "GenericHostType:{0}{1}", parentPrefix, Types[0].GetRootName()); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => GetSpecificTypeNoThrow() ?? Types[0]; + + public override object Target => this; + + public override object InvokeTarget + { + get + { + GetSpecificType(); + return null; + } + } + + public override object DynamicInvokeTarget => GetSpecificType(); + + public override HostTargetFlags GetFlags(IHostContext context) + { + var type = GetSpecificTypeNoThrow(); + return (type != null) ? HostTargetFlags.AllowStaticMembers : HostTargetFlags.None; + } + + public override string[] GetAuxPropertyNames(IHostContext context, BindingFlags bindFlags) + { + var type = GetSpecificTypeNoThrow(); + if (type != null) + { + return type.GetScriptableNestedTypes(context, bindFlags).Select(testType => testType.GetRootName()).Distinct().ToArray(); + } + + return ArrayHelpers.GetEmptyArray(); + } + + public override bool TryInvokeAuxMember(IHostContext context, string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + var type = GetSpecificTypeNoThrow(); + if (type != null) + { + var nestedTypes = type.GetScriptableNestedTypes(context, invokeFlags).Where(testType => string.Equals(testType.GetRootName(), name, invokeFlags.GetMemberNameComparison())).ToIList(); + if (nestedTypes.Count > 0) + { + var tempResult = Wrap(nestedTypes.Select(testType => testType.ApplyTypeArguments(type.GetGenericArguments())).ToArray()); + if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + { + if (tempResult.TryInvoke(context, invokeFlags, args, bindArgs, out result)) + { + return true; + } + + if (!invokeFlags.HasFlag(BindingFlags.GetField) && !invokeFlags.HasFlag(BindingFlags.GetProperty)) + { + return false; + } + } + + result = tempResult; + return true; + } + } + + result = null; + return false; + } + + public override bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + if (!invokeFlags.HasFlag(BindingFlags.InvokeMethod) || (args.Length < 1)) + { + result = null; + return false; + } + + if (!args.All(arg => arg is HostType)) + { + throw new ArgumentException("Invalid generic type argument"); + } + + var templates = Types.Where(type => !type.IsSpecific()).ToArray(); + var typeArgs = args.Cast().Select(hostType => hostType.GetTypeArg()).ToArray(); + + var template = templates.FirstOrDefault(testTemplate => testTemplate.GetGenericParamCount() == typeArgs.Length); + if (template == null) + { + throw new TypeLoadException(MiscHelpers.FormatInvariant("Could not find a matching generic type definition for '{0}'", templates[0].GetRootName())); + } + + result = Wrap(template.MakeSpecificType(typeArgs)); + return true; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return Invocability.Delegate; + } + + #endregion + + #region IScriptableObject implementation + + void IScriptableObject.OnExposedToScriptCode(ScriptEngine engine) + { + if (engine != null) + { + var specificType = GetSpecificTypeNoThrow(); + if (specificType != null) + { + engine.ProcessExtensionMethodType(specificType); + } + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostType.cs.meta b/Unity/Package/Runtime/HostType.cs.meta new file mode 100644 index 000000000..dd3434e9a --- /dev/null +++ b/Unity/Package/Runtime/HostType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 186b2ec61b41ae840a75aa96c84576db +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostTypeCollection.cs b/Unity/Package/Runtime/HostTypeCollection.cs new file mode 100644 index 000000000..68f035665 --- /dev/null +++ b/Unity/Package/Runtime/HostTypeCollection.cs @@ -0,0 +1,381 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.COM; +using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a scriptable collection of host types. + /// + /// + /// Host type collections provide convenient scriptable access to all the types defined in one + /// or more host assemblies. They are hierarchical collections where leaf nodes represent types + /// and parent nodes represent namespaces. For example, if an assembly contains a type named + /// "Acme.Gadgets.Button", the corresponding collection will have a property named "Acme" whose + /// value is an object with a property named "Gadgets" whose value is an object with a property + /// named "Button" whose value represents the Acme.Gadgets.Button host type. Use + /// AddHostObject to expose a host + /// type collection to script code. + /// + public class HostTypeCollection : PropertyBag + { + private static readonly Predicate defaultFilter = type => true; + private static readonly TypeComparer typeComparer = new TypeComparer(); + + /// + /// Initializes a new host type collection. + /// + public HostTypeCollection() + : base(true) + { + } + + /// + /// Initializes a new host type collection with types from one or more assemblies. + /// + /// The assemblies that contain the types with which to initialize the collection. + public HostTypeCollection(params Assembly[] assemblies) + : base(true) + { + MiscHelpers.VerifyNonNullArgument(assemblies, nameof(assemblies)); + Array.ForEach(assemblies, AddAssembly); + } + + /// + /// Initializes a new host type collection with types from one or more assemblies. The + /// assemblies are specified by name. + /// + /// The names of the assemblies that contain the types with which to initialize the collection. + public HostTypeCollection(params string[] assemblyNames) + : base(true) + { + MiscHelpers.VerifyNonNullArgument(assemblyNames, nameof(assemblyNames)); + Array.ForEach(assemblyNames, AddAssembly); + } + + /// + /// Initializes a new host type collection with selected types from one or more assemblies. + /// + /// A filter for selecting the types to add. + /// The assemblies that contain the types with which to initialize the collection. + public HostTypeCollection(Predicate filter, params Assembly[] assemblies) + { + MiscHelpers.VerifyNonNullArgument(assemblies, nameof(assemblies)); + Array.ForEach(assemblies, assembly => AddAssembly(assembly, filter)); + } + + /// + /// Initializes a new host type collection with selected types from one or more assemblies. + /// The assemblies are specified by name. + /// + /// A filter for selecting the types to add. + /// The names of the assemblies that contain the types with which to initialize the collection. + public HostTypeCollection(Predicate filter, params string[] assemblyNames) + { + MiscHelpers.VerifyNonNullArgument(assemblyNames, nameof(assemblyNames)); + Array.ForEach(assemblyNames, assemblyName => AddAssembly(assemblyName, filter)); + } + + /// + /// Adds types from an assembly to a host type collection. + /// + /// The assembly that contains the types to add. + public void AddAssembly(Assembly assembly) + { + MiscHelpers.VerifyNonNullArgument(assembly, nameof(assembly)); + assembly.GetAllTypes().Where(type => type.IsImportable(null)).ForEach(AddType); + } + + /// + /// Adds types from an assembly to a host type collection. The assembly is specified by name. + /// + /// The name of the assembly that contains the types to add. + public void AddAssembly(string assemblyName) + { + MiscHelpers.VerifyNonBlankArgument(assemblyName, nameof(assemblyName), "Invalid assembly name"); + AddAssembly(Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName))); + } + + /// + /// Adds selected types from an assembly to a host type collection. + /// + /// The assembly that contains the types to add. + /// A filter for selecting the types to add. + public void AddAssembly(Assembly assembly, Predicate filter) + { + MiscHelpers.VerifyNonNullArgument(assembly, nameof(assembly)); + var activeFilter = filter ?? defaultFilter; + assembly.GetAllTypes().Where(type => type.IsImportable(null) && activeFilter(type)).ForEach(AddType); + } + + /// + /// Adds selected types from an assembly to a host type collection. The assembly is + /// specified by name. + /// + /// The name of the assembly that contains the types to add. + /// A filter for selecting the types to add. + public void AddAssembly(string assemblyName, Predicate filter) + { + MiscHelpers.VerifyNonBlankArgument(assemblyName, nameof(assemblyName), "Invalid assembly name"); + AddAssembly(Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName)), filter); + } + + /// + /// Adds a type to a host type collection. + /// + /// The type to add. + public void AddType(Type type) + { + MiscHelpers.VerifyNonNullArgument(type, nameof(type)); + AddType(HostType.Wrap(type)); + } + + /// + /// Adds a type to a host type collection. The type is specified by name. + /// + /// The fully qualified name of the type to add. + /// Optional generic type arguments. + public void AddType(string typeName, params Type[] typeArgs) + { + AddType(TypeHelpers.ImportType(typeName, null, false, typeArgs)); + } + + /// + /// Adds a type to a host type collection. The type is specified by type name and assembly name. + /// + /// The fully qualified name of the type to add. + /// The name of the assembly that contains the type to add. + /// Optional generic type arguments. + public void AddType(string typeName, string assemblyName, params Type[] typeArgs) + { + AddType(TypeHelpers.ImportType(typeName, assemblyName, true, typeArgs)); + } + + /// + /// Locates a namespace within a host type collection. + /// + /// The full name of the namespace to locate. + /// The node that represents the namespace if it was found, null otherwise. + public PropertyBag GetNamespaceNode(string name) + { + MiscHelpers.VerifyNonNullArgument(name, nameof(name)); + + PropertyBag namespaceNode = this; + + var segments = name.Split('.'); + foreach (var segment in segments) + { + if (!namespaceNode.TryGetValue(segment, out var node)) + { + return null; + } + + namespaceNode = node as PropertyBag; + if (namespaceNode == null) + { + return null; + } + } + + return namespaceNode; + } + + internal void AddEnumTypeInfo(ITypeInfo typeInfo) + { + AddEnumTypeInfoInternal(typeInfo); + } + + private PropertyBag AddEnumTypeInfoInternal(ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + if (attrScope.Value.typekind == TYPEKIND.TKIND_ALIAS) + { + typeInfo.GetRefTypeInfo(unchecked((int)attrScope.Value.tdescAlias.lpValue.ToInt64()), out var refTypeInfo); + + var node = AddEnumTypeInfoInternal(refTypeInfo); + if (node != null) + { + var locator = typeInfo.GetManagedName(); + + var segments = locator.Split('.'); + if (segments.Length > 0) + { + var namespaceNode = GetOrCreateNamespaceNode(locator); + if (namespaceNode != null) + { + namespaceNode.SetPropertyNoCheck(segments.Last(), node); + return node; + } + } + } + } + else if (attrScope.Value.typekind == TYPEKIND.TKIND_ENUM) + { + var node = GetOrCreateEnumTypeInfoNode(typeInfo); + if (node != null) + { + var count = attrScope.Value.cVars; + for (var index = 0; index < count; index++) + { + using (var varDescScope = typeInfo.CreateVarDescScope(index)) + { + if (varDescScope.Value.varkind == VARKIND.VAR_CONST) + { + var name = typeInfo.GetMemberName(varDescScope.Value.memid); + node.SetPropertyNoCheck(name, MiscHelpers.GetObjectForVariant(varDescScope.Value.desc.lpvarValue)); + } + } + } + + return node; + } + } + } + + return null; + } + + private PropertyBag GetOrCreateEnumTypeInfoNode(ITypeInfo typeInfo) + { + var locator = typeInfo.GetManagedName(); + + var segments = locator.Split('.'); + if (segments.Length < 1) + { + return null; + } + + PropertyBag enumTypeInfoNode = this; + foreach (var segment in segments) + { + PropertyBag innerNode; + + if (!enumTypeInfoNode.TryGetValue(segment, out var node)) + { + innerNode = new PropertyBag(true); + enumTypeInfoNode.SetPropertyNoCheck(segment, innerNode); + } + else + { + innerNode = node as PropertyBag; + if (innerNode == null) + { + throw new OperationCanceledException(MiscHelpers.FormatInvariant("Enumeration conflicts with '{0}' at '{1}'", node.GetFriendlyName(), locator)); + } + } + + enumTypeInfoNode = innerNode; + } + + return enumTypeInfoNode; + } + + private void AddType(HostType hostType) + { + MiscHelpers.VerifyNonNullArgument(hostType, nameof(hostType)); + foreach (var type in hostType.Types) + { + var namespaceNode = GetOrCreateNamespaceNode(type); + if (namespaceNode != null) + { + AddTypeToNamespaceNode(namespaceNode, type); + } + } + } + + private PropertyBag GetOrCreateNamespaceNode(Type type) + { + return GetOrCreateNamespaceNode(type.GetLocator()); + } + + private PropertyBag GetOrCreateNamespaceNode(string locator) + { + var segments = locator.Split('.'); + if (segments.Length < 1) + { + return null; + } + + PropertyBag namespaceNode = this; + foreach (var segment in segments.Take(segments.Length - 1)) + { + PropertyBag innerNode; + + if (!namespaceNode.TryGetValue(segment, out var node)) + { + innerNode = new PropertyBag(true); + namespaceNode.SetPropertyNoCheck(segment, innerNode); + } + else + { + innerNode = node as PropertyBag; + if (innerNode == null) + { + throw new OperationCanceledException(MiscHelpers.FormatInvariant("Namespace conflicts with '{0}' at '{1}'", node.GetFriendlyName(), locator)); + } + } + + namespaceNode = innerNode; + } + + return namespaceNode; + } + + private static void AddTypeToNamespaceNode(PropertyBag node, Type type) + { + var name = type.GetRootName(); + if (!node.TryGetValue(name, out var value)) + { + node.SetPropertyNoCheck(name, HostType.Wrap(type)); + return; + } + + if (value is HostType hostType) + { + var types = type.ToEnumerable().Concat(hostType.Types).ToArray(); + + var groups = types.GroupBy(testType => testType.GetGenericParamCount()).ToIList(); + if (groups.Any(group => group.Count() > 1)) + { + types = groups.Select(ResolveTypeConflict).ToArray(); + } + + node.SetPropertyNoCheck(name, HostType.Wrap(types)); + return; + } + + if (value is PropertyBag) + { + throw new OperationCanceledException(MiscHelpers.FormatInvariant("Type conflicts with namespace at '{0}'", type.GetLocator())); + } + + throw new OperationCanceledException(MiscHelpers.FormatInvariant("Type conflicts with '{0}' at '{1}'", value.GetFriendlyName(), type.GetLocator())); + } + + private static Type ResolveTypeConflict(IEnumerable types) + { + var typeList = types.Distinct(typeComparer).ToIList(); + return typeList.SingleOrDefault(type => type.IsPublic) ?? typeList[0]; + } + + #region Nested type : TypeComparer + + private sealed class TypeComparer : EqualityComparer + { + public override bool Equals(Type x, Type y) => (x == y) || (x.AssemblyQualifiedName == y.AssemblyQualifiedName); + + public override int GetHashCode(Type type) => type.AssemblyQualifiedName.GetHashCode(); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostTypeCollection.cs.meta b/Unity/Package/Runtime/HostTypeCollection.cs.meta new file mode 100644 index 000000000..b43acf175 --- /dev/null +++ b/Unity/Package/Runtime/HostTypeCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 303b0922206fa4d44ad8994b79e4eb97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/HostVariable.cs b/Unity/Package/Runtime/HostVariable.cs new file mode 100644 index 000000000..8e8250bbc --- /dev/null +++ b/Unity/Package/Runtime/HostVariable.cs @@ -0,0 +1,181 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Dynamic; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal interface IHostVariable + { + Type Type { get; } + object Value { get; set; } + } + + internal abstract class HostVariable : HostTarget + { + private static readonly string[] auxPropertyNames = { "out", "ref", "value" }; + + public override string[] GetAuxPropertyNames(IHostContext context, BindingFlags bindFlags) + { + return auxPropertyNames; + } + } + + internal sealed class HostVariable : HostVariable, IHostVariable + { + public HostVariable(T initValue) + { + if ((typeof(T) == typeof(Undefined)) || (typeof(T) == typeof(VoidResult))) + { + throw new NotSupportedException("Unsupported variable type"); + } + + if (typeof(HostItem).IsAssignableFrom(typeof(T)) || typeof(HostTarget).IsAssignableFrom(typeof(T))) + { + throw new NotSupportedException("Unsupported variable type"); + } + + if ((initValue is HostItem) || (initValue is HostTarget)) + { + throw new NotSupportedException("Unsupported value type"); + } + + Value = initValue; + } + + public T Value { get; set; } + // Be careful when renaming or deleting this property; it is accessed by name in the + // expression tree construction code in DelegateFactory.CreateComplexDelegate(). + + #region Object overrides + + public override string ToString() + { + var objectName = Value.GetFriendlyName(typeof(T)); + return MiscHelpers.FormatInvariant("HostVariable:{0}", objectName); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => typeof(T); + + public override object Target => Value; + + public override object InvokeTarget => Value; + + public override object DynamicInvokeTarget => Value; + + public override HostTargetFlags GetFlags(IHostContext context) + { + var flags = HostTargetFlags.AllowInstanceMembers | HostTargetFlags.AllowExtensionMethods; + if (context.Engine.ExposeHostObjectStaticMembers) + { + flags |= HostTargetFlags.AllowStaticMembers; + } + + return flags; + } + + public override bool TryInvokeAuxMember(IHostContext context, string name, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + const BindingFlags getPropertyFlags = + BindingFlags.GetField | + BindingFlags.GetProperty; + + const BindingFlags setPropertyFlags = + BindingFlags.SetProperty | + BindingFlags.PutDispProperty | + BindingFlags.PutRefDispProperty; + + if (string.Equals(name, "out", invokeFlags.GetMemberNameComparison())) + { + if ((invokeFlags & getPropertyFlags) != 0) + { + result = new OutArg(this); + return true; + } + } + else if (string.Equals(name, "ref", invokeFlags.GetMemberNameComparison())) + { + if ((invokeFlags & getPropertyFlags) != 0) + { + result = new RefArg(this); + return true; + } + } + else if (string.Equals(name, "value", invokeFlags.GetMemberNameComparison())) + { + if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + { + if (InvokeHelpers.TryInvokeObject(context, Value, invokeFlags, args, bindArgs, typeof(IDynamicMetaObjectProvider).IsAssignableFrom(typeof(T)), out result)) + { + return true; + } + + if (invokeFlags.HasFlag(BindingFlags.GetField) && (args.Length < 1)) + { + result = context.Engine.PrepareResult(Value, ScriptMemberFlags.None, false); + return true; + } + + result = null; + return false; + } + + if ((invokeFlags & getPropertyFlags) != 0) + { + result = context.Engine.PrepareResult(Value, ScriptMemberFlags.None, false); + return true; + } + + if ((invokeFlags & setPropertyFlags) != 0) + { + if (args.Length == 1) + { + result = context.Engine.PrepareResult(((IHostVariable)this).Value = args[0], typeof(T), ScriptMemberFlags.None, false); + return true; + } + } + } + + result = null; + return false; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return typeof(T).GetInvocability(context, bindFlags, ignoreDynamic); + } + + #endregion + + #region IHostVariable implementation + + object IHostVariable.Value + { + get => Value; + + set + { + if (!typeof(T).IsAssignableFromValue(ref value)) + { + throw new InvalidOperationException("Assignment invalid due to type mismatch"); + } + + if ((value is HostItem) || (value is HostTarget)) + { + throw new NotSupportedException("Unsupported value type"); + } + + Value = (T)value; + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/HostVariable.cs.meta b/Unity/Package/Runtime/HostVariable.cs.meta new file mode 100644 index 000000000..4f43b7bb0 --- /dev/null +++ b/Unity/Package/Runtime/HostVariable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 398d634f36ec12c479abc3d75950d700 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/IScriptEngine.cs b/Unity/Package/Runtime/IScriptEngine.cs new file mode 100644 index 000000000..4712b2781 --- /dev/null +++ b/Unity/Package/Runtime/IScriptEngine.cs @@ -0,0 +1,1241 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a script engine. + /// + public interface IScriptEngine : IDisposable + { + /// + /// Gets the name associated with the script engine instance. + /// + string Name { get; } + + /// + /// Gets the script engine's recommended file name extension for script files. + /// + string FileNameExtension { get; } + + /// + /// Allows script code to access non-host resources. + /// + /// + /// By setting this property to a type you declare that script code running in the current + /// script engine is to be treated as if it were part of that type's implementation. Doing + /// so does not expose any host resources to script code, but it affects which host + /// resources are importable and which members of exposed resources are accessible. + /// + Type AccessContext { get; set; } + + /// + /// Gets or sets the default script access setting for all members of exposed objects. + /// + /// + /// Use , , or + /// their subclasses to override this property for individual types and members. Note that + /// this property has no effect on the method binding algorithm. If a script-based call is + /// bound to a method that is blocked by this property, it will be rejected even if an + /// overload exists that could receive the call. + /// + ScriptAccess DefaultAccess { get; set; } + + /// + /// Enables or disables access restrictions for anonymous types. + /// + /// + /// Anonymous types are + /// internal + /// and therefore accessible only within the same assembly, but ClearScript 5.5.3 and + /// earlier permitted access to the properties of an object even if its type was + /// internal. Newer versions strictly enforce , but because + /// anonymous types are particularly useful for scripting, ClearScript by default continues + /// to expose their properties to external contexts. To override this behavior and enable + /// normal access restrictions for anonymous types, set this property to true. + /// + bool EnforceAnonymousTypeAccess { get; set; } + + /// + /// Controls whether host objects provide access to the static members of their exposed types to script code. + /// + bool ExposeHostObjectStaticMembers { get; set; } + + /// + /// Enables or disables extension method support. + /// + bool DisableExtensionMethods { get; set; } + + /// + /// Enables or disables script code formatting. + /// + /// + /// When this property is set to true, the script engine may format script code + /// before executing or compiling it. This is intended to facilitate interactive debugging. + /// The formatting operation currently includes stripping leading and trailing blank lines + /// and removing global indentation. + /// + bool FormatCode { get; set; } + + /// + /// Controls whether script code is permitted to use reflection. + /// + /// + /// When this property is set to true, script code running in the current script + /// engine is permitted to use reflection. This affects + /// Object.GetType(), + /// Exception.GetType(), + /// Exception.TargetSite, + /// Delegate.Method, + /// and . + /// By default, any attempt to invoke these members from script code results in an + /// exception. + /// + bool AllowReflection { get; set; } + + /// + /// Enables or disables type restriction for field, property, and method return values. + /// + /// + /// When this property is set to true, script code running in the current script + /// engine has access to the runtime types of all exposed host resources, which by default + /// are restricted to their declared types. The default behavior is a general requirement + /// for correct method binding, so setting this property to true is not recommended. + /// + /// + bool DisableTypeRestriction { get; set; } + + /// + /// Enables or disables type restriction for array and list elements retrieved by index. + /// + /// + /// In ClearScript 5.4.4 and earlier, indexed array and list elements were exempt from type + /// restriction. ClearScript 5.4.5 introduced a breaking change to correct this, but you can + /// set this property to true to restore the exemption if you have older script code + /// that depends on it. + /// + /// + bool DisableListIndexTypeRestriction { get; set; } + + /// + /// Enables or disables null wrapping for field, property, and method return values. + /// + /// + /// When this property is set to true, all field, property, and method return values + /// are marshaled with full .NET type information even if they are null. Note that + /// such values will always fail equality comparison with JavaScript's + /// null, + /// VBScript's + /// Nothing, + /// and other similar values. Instead, use or + /// to perform such a comparison. + /// + /// + /// + bool EnableNullResultWrapping { get; set; } + + /// + /// Enables or disables floating point narrowing. + /// + /// + /// When this property is set to true, no attempt is made to convert floating-point + /// values imported from the script engine to the narrowest equivalent .NET representation. + /// The default behavior is more likely to result in successful method binding in specific + /// scenarios, so setting this property to true is not recommended. + /// + bool DisableFloatNarrowing { get; set; } + + /// + /// Enables or disables dynamic method binding. + /// + /// + /// When this property is set to true, the script engine bypasses the default method + /// binding algorithm and uses reflection-based method binding instead. This approach + /// abandons support for generic type inference and other features, but it avoids engaging + /// the dynamic infrastructure. + /// + /// + bool DisableDynamicBinding { get; set; } + + /// + /// Enables or disables the use of reflection-based method binding as a fallback. + /// + /// + /// + /// When this property is set to true, the script engine attempts to use + /// reflection-based method binding when the default method binding algorithm fails. This + /// approach reduces type safety, but it may be useful for running legacy scripts that rely + /// on the specific behavior of reflection-based method binding. + /// + /// + /// This property has no effect when is set to + /// true. + /// + /// + bool UseReflectionBindFallback { get; set; } + + /// + /// Enables or disables automatic host variable tunneling for by-reference arguments to script functions and delegates. + /// + /// + /// When this property is set to true, the script engine replaces by-reference + /// arguments to script functions and delegates with host variables, allowing script code + /// to simulate output arguments if the script language does not support them natively. + /// + /// + bool EnableAutoHostVariables { get; set; } + + /// + /// Gets or sets the script engine's undefined import value. + /// + /// + /// Some script languages support one or more special non-null values that represent + /// nonexistent, missing, unknown, or undefined data. When such a value is marshaled to the + /// host, the script engine maps it to the value of this property. The default value is + /// Undefined.Value. + /// + object UndefinedImportValue { get; set; } + + /// + /// Gets or sets the script engine's null export value. + /// + /// + /// + /// When a null object reference is marshaled to script code, the script engine maps it to + /// the value of this property. The default value is simply null, which corresponds + /// to null or its closest equivalent in the script language. Other useful + /// possibilities include + /// Undefined.Value and + /// Nothing.Value. + /// + /// + /// Note that , + /// , and + /// MarshalNullAsDispatch + /// all take precedence over this property. + /// + /// + object NullExportValue { get; set; } + + /// + /// Gets or sets the script engine's void result export value. + /// + /// + /// Some script languages expect every subroutine call to return a value. When script code + /// written in such a language invokes a host method that explicitly returns no value (such + /// as a C# + /// void + /// method), the script engine returns the value of this property as a dummy result. The + /// default value is VoidResult.Value. + /// + object VoidResultValue { get; set; } + + /// + /// Gets or sets a callback that can be used to halt script execution. + /// + /// + /// During script execution the script engine periodically invokes this callback to + /// determine whether it should continue. If the callback returns false, the script + /// engine terminates script execution and throws an exception. + /// + ContinuationCallback ContinuationCallback { get; set; } + + /// + /// Allows the host to access script resources dynamically. + /// + /// + /// The value of this property is an object that is bound to the script engine's root + /// namespace. It dynamically supports properties and methods that correspond to global + /// script objects and functions. + /// + dynamic Script { get; } + + /// + /// Allows the host to access script resources. + /// + /// + /// The value of this property is an object that is bound to the script engine's root + /// namespace. It allows you to access global script resources via the + /// class interface. Doing so is likely to outperform + /// dynamic access via . + /// + ScriptObject Global { get; } + + /// + /// Gets or sets the script engine's document settings. + /// + DocumentSettings DocumentSettings { get; set; } + + /// + /// Gets or sets the script engine's custom attribute loader. + /// + /// + /// By default, all script engines use the + /// global custom attribute loader. + /// + CustomAttributeLoader CustomAttributeLoader { get; set; } + + /// + /// Allows the host to attach arbitrary data to the script engine. + /// + object HostData { get; set; } + + /// + /// Exposes a host object to script code. + /// + /// A name for the new global script item that will represent the object. + /// The object to expose. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddHostObject(string itemName, object target); + + /// + /// Exposes a host object to script code with the specified options. + /// + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The object to expose. + /// + /// + /// Once a host object is exposed to script code, its members are accessible via the script + /// language's native syntax for member access. The following table provides details about + /// the mapping between host members and script-accessible properties and methods. + /// + /// + /// + /// + /// Member Type + /// Exposed As + /// Remarks + /// + /// + /// Constructor + /// N/A + /// + /// To invoke a constructor from script code, call + /// HostFunctions.newObj(T). + /// + /// + /// + /// Property/Field + /// Property + /// N/A + /// + /// + /// Method + /// Method + /// + /// Overloaded host methods are merged into a single script-callable method. At + /// runtime the correct host method is selected based on the argument types. + /// + /// + /// + /// Generic Method + /// Method + /// + /// The ClearScript library supports dynamic C#-like type inference when invoking + /// generic methods. However, some methods require explicit type arguments. To call + /// such a method from script code, you must place the required number of + /// host type objects + /// at the beginning of the argument list. Doing so for methods that do not require + /// explicit type arguments is optional. + /// + /// + /// + /// Extension Method + /// Method + /// + /// Extension methods are available if the type that implements them has been + /// exposed in the current script engine. + /// + /// + /// + /// Indexer + /// Property + /// + /// Indexers appear as properties named "Item" that accept one or more index values + /// as arguments. In addition, objects that implement expose + /// properties with numeric names that match their valid indices. This includes + /// one-dimensional host arrays and other collections. Multidimensional host arrays + /// do not expose functional indexers; you must use + /// Array.GetValue + /// and + /// Array.SetValue + /// instead. + /// + /// + /// + /// Event + /// Property + /// + /// Events are exposed as read-only properties of type . + /// + /// + /// + /// + /// + void AddHostObject(string itemName, HostItemFlags flags, object target); + + /// + /// Exposes a host object to script code with the specified type restriction. + /// + /// The type whose members are to be made accessible from script code. + /// A name for the new global script item that will represent the object. + /// The object to expose. + /// + /// + /// This method can be used to restrict script access to the members of a particular + /// interface or base class. + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddRestrictedHostObject(string itemName, T target); + + /// + /// Exposes a host object to script code with the specified type restriction and options. + /// + /// The type whose members are to be made accessible from script code. + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The object to expose. + /// + /// + /// This method can be used to restrict script access to the members of a particular + /// interface or base class. + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddRestrictedHostObject(string itemName, HostItemFlags flags, T target); + + /// + /// Creates a COM/ActiveX object and exposes it to script code. The registered class is + /// specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the object. + /// The programmatic identifier (ProgID) of the registered class to instantiate. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMObject(string itemName, string progID); + + /// + /// Creates a COM/ActiveX object on the specified server and exposes it to script code. The + /// registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the object. + /// The programmatic identifier (ProgID) of the registered class to instantiate. + /// The name of the server on which to create the object. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMObject(string itemName, string progID, string serverName); + + /// + /// Creates a COM/ActiveX object and exposes it to script code with the specified options. + /// The registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The programmatic identifier (ProgID) of the registered class to instantiate. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMObject(string itemName, HostItemFlags flags, string progID); + + /// + /// Creates a COM/ActiveX object on the specified server and exposes it to script code with + /// the specified options. The registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The programmatic identifier (ProgID) of the registered class to instantiate. + /// The name of the server on which to create the object. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMObject(string itemName, HostItemFlags flags, string progID, string serverName); + + /// + /// Creates a COM/ActiveX object and exposes it to script code. The registered class is + /// specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the object. + /// The class identifier (CLSID) of the registered class to instantiate. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMObject(string itemName, Guid clsid); + + /// + /// Creates a COM/ActiveX object on the specified server and exposes it to script code. The + /// registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the object. + /// The class identifier (CLSID) of the registered class to instantiate. + /// The name of the server on which to create the object. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMObject(string itemName, Guid clsid, string serverName); + + /// + /// Creates a COM/ActiveX object and exposes it to script code with the specified options. + /// The registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The class identifier (CLSID) of the registered class to instantiate. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid); + + /// + /// Creates a COM/ActiveX object on the specified server and exposes it to script code with + /// the specified options. The registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the object. + /// A value that selects options for the operation. + /// The class identifier (CLSID) of the registered class to instantiate. + /// The name of the server on which to create the object. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid, string serverName); + + /// + /// Exposes a host type to script code with a default name. + /// + /// The type to expose. + /// + /// + /// This method uses 's name for the new global script item that + /// will represent it. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(Type type); + + /// + /// Exposes a host type to script code with a default name and the specified options. + /// + /// A value that selects options for the operation. + /// The type to expose. + /// + /// + /// This method uses 's name for the new global script item that + /// will represent it. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(HostItemFlags flags, Type type); + + /// + /// Exposes a host type to script code. + /// + /// A name for the new global script item that will represent the type. + /// The type to expose. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, Type type); + + /// + /// Exposes a host type to script code with the specified options. + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The type to expose. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, HostItemFlags flags, Type type); + + /// + /// Exposes a host type to script code. The type is specified by name. + /// + /// A name for the new global script item that will represent the type. + /// The fully qualified name of the type to expose. + /// Optional generic type arguments. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, string typeName, params Type[] typeArgs); + + /// + /// Exposes a host type to script code with the specified options. The type is specified by name. + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The fully qualified name of the type to expose. + /// Optional generic type arguments. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, HostItemFlags flags, string typeName, params Type[] typeArgs); + + /// + /// Exposes a host type to script code. The type is specified by type name and assembly name. + /// + /// A name for the new global script item that will represent the type. + /// The fully qualified name of the type to expose. + /// The name of the assembly that contains the type to expose. + /// Optional generic type arguments. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, string typeName, string assemblyName, params Type[] typeArgs); + + /// + /// Exposes a host type to script code with the specified options. The type is specified by + /// type name and assembly name. + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The fully qualified name of the type to expose. + /// The name of the assembly that contains the type to expose. + /// Optional generic type arguments. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostType(string itemName, HostItemFlags flags, string typeName, string assemblyName, params Type[] typeArgs); + + /// + /// Exposes host types to script code. + /// + /// The types to expose. + /// + /// + /// This method uses each specified type's name for the new global script item that will + /// represent it. + /// + /// + /// Host types are exposed to script code in the form of objects whose properties and + /// methods are bound to the type's static members and nested types. If the type has + /// generic parameters, the corresponding object will be invocable with type arguments to + /// yield a specific type. + /// + /// + /// For more information about the mapping between host members and script-callable + /// properties and methods, see . + /// + /// + void AddHostTypes(params Type[] types); + + /// + /// Imports a COM/ActiveX type and exposes it to script code. The registered class is + /// specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the type. + /// The programmatic identifier (ProgID) of the registered class to import. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMType(string itemName, string progID); + + /// + /// Imports a COM/ActiveX type from the specified server and exposes it to script code. The + /// registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the type. + /// The programmatic identifier (ProgID) of the registered class to import. + /// The name of the server from which to import the type. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMType(string itemName, string progID, string serverName); + + /// + /// Imports a COM/ActiveX type and exposes it to script code with the specified options. + /// The registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The programmatic identifier (ProgID) of the registered class to import. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMType(string itemName, HostItemFlags flags, string progID); + + /// + /// Imports a COM/ActiveX type from the specified server and exposes it to script code with + /// the specified options. The registered class is specified by programmatic identifier (ProgID). + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The programmatic identifier (ProgID) of the registered class to import. + /// The name of the server from which to import the type. + /// + /// + /// The argument can be a class identifier (CLSID) in standard + /// GUID format with braces (e.g., "{0D43FE01-F093-11CF-8940-00A0C9054228}"). + /// + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + /// + void AddCOMType(string itemName, HostItemFlags flags, string progID, string serverName); + + /// + /// Imports a COM/ActiveX type and exposes it to script code. The registered class is + /// specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the type. + /// The class identifier (CLSID) of the registered class to import. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMType(string itemName, Guid clsid); + + /// + /// Imports a COM/ActiveX type from the specified server and exposes it to script code. The + /// registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the type. + /// The class identifier (CLSID) of the registered class to import. + /// The name of the server from which to import the type. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMType(string itemName, Guid clsid, string serverName); + + /// + /// Imports a COM/ActiveX type and exposes it to script code with the specified options. + /// The registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The class identifier (CLSID) of the registered class to import. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMType(string itemName, HostItemFlags flags, Guid clsid); + + /// + /// Imports a COM/ActiveX type from the specified server and exposes it to script code with + /// the specified options. The registered class is specified by class identifier (CLSID). + /// + /// A name for the new global script item that will represent the type. + /// A value that selects options for the operation. + /// The class identifier (CLSID) of the registered class to import. + /// The name of the server from which to import the type. + /// + /// For information about the mapping between host members and script-callable properties + /// and methods, see . + /// + void AddCOMType(string itemName, HostItemFlags flags, Guid clsid, string serverName); + + /// + /// Executes script code. + /// + /// The script code to execute. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as a statement. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with an automatically selected name. This document will not be discarded + /// after execution. + /// + /// + void Execute(string code); + + /// + /// Executes script code with an associated document name. + /// + /// A document name for the script code. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to execute. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as a statement. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with the specified name. This document will not be discarded after execution. + /// + /// + void Execute(string documentName, string code); + + /// + /// Executes script code with an associated document name, optionally discarding the document after execution. + /// + /// A document name for the script code. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// True to discard the script document after execution, false otherwise. + /// The script code to execute. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as a statement. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with the specified name. Discarding this document removes it from view but + /// has no effect on the script engine. Only Windows Script engines honor + /// . + /// + /// + void Execute(string documentName, bool discard, string code); + + /// + /// Executes script code with the specified document meta-information. + /// + /// A structure containing meta-information for the script document. + /// The script code to execute. + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as a statement. + /// + void Execute(DocumentInfo documentInfo, string code); + + /// + /// Loads and executes a script document. + /// + /// A string specifying the document to be loaded and executed. + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as a statement. + /// + void ExecuteDocument(string specifier); + + /// + /// Loads and executes a document with the specified category. + /// + /// A string specifying the document to be loaded and executed. + /// An optional category for the requested document. + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as a statement. + /// + void ExecuteDocument(string specifier, DocumentCategory category); + + /// + /// Loads and executes a document with the specified category and context callback. + /// + /// A string specifying the document to be loaded and executed. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as a statement. + /// + void ExecuteDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback); + + /// + /// Executes script code as a command. + /// + /// The script command to execute. + /// The command output. + /// + /// This method is similar to but optimized for command + /// consoles. The specified command must be limited to a single expression or statement. + /// Script engines can override this method to customize command execution as well as the + /// process of converting the result to a string for console output. + /// + string ExecuteCommand(string command); + + /// + /// Evaluates script code. + /// + /// The script code to evaluate. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as an expression. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with an automatically selected name. This document will be discarded after + /// execution. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object Evaluate(string code); + + /// + /// Evaluates script code with an associated document name. + /// + /// A document name for the script code. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to evaluate. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as an expression. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with the specified name. This document will be discarded after execution. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object Evaluate(string documentName, string code); + + /// + /// Evaluates script code with an associated document name, optionally discarding the document after execution. + /// + /// A document name for the script code. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// True to discard the script document after execution, false otherwise. + /// The script code to evaluate. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as an expression. + /// + /// + /// If a debugger is attached, it will present the specified script code to the user as a + /// document with the specified name. Discarding this document removes it from view but + /// has no effect on the script engine. Only Windows Script engines honor + /// . + /// + /// + /// The following table summarizes the types of result values that script code can return. + /// + /// + /// Type + /// Returned As + /// Remarks + /// + /// + /// String + /// System.String + /// N/A + /// + /// + /// Boolean + /// System.Boolean + /// N/A + /// + /// + /// Number + /// System.Int32 or System.Double + /// + /// Other numeric types are possible. The exact conversions between script and .NET + /// numeric types are defined by the script engine. + /// + /// + /// + /// Null Reference + /// null + /// N/A + /// + /// + /// Undefined + /// + /// + /// This represents JavaScript's + /// undefined, + /// VBScript's + /// Empty, + /// etc. + /// + /// + /// + /// Void + /// + /// + /// This is returned when script code forwards the result of a host method that returns no value. + /// + /// + /// + /// Host Object + /// Native .NET type + /// + /// This includes all .NET types not mentioned above, including value types (enums, + /// structs, etc.), and instances of all other classes. Script code can only create + /// these objects by invoking a host method or constructor. They are returned to + /// the host in their native .NET form. + /// + /// + /// + /// Script Object + /// + /// + /// This includes all native script objects that have no .NET representation. C#'s + /// dynamic + /// keyword provides a convenient way to access them. + /// + /// + /// + /// Other + /// Unspecified + /// + /// This includes host types and other ClearScript-specific objects intended for + /// script code use only. It may also include language-specific values that the + /// ClearScript library does not support. + /// + /// + /// + /// + /// + object Evaluate(string documentName, bool discard, string code); + + /// + /// Evaluates script code with the specified document meta-information. + /// + /// A structure containing meta-information for the script document. + /// The script code to evaluate. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets the specified script code as an expression. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object Evaluate(DocumentInfo documentInfo, string code); + + /// + /// Loads and evaluates a script document. + /// + /// A string specifying the document to be loaded and evaluated. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as an expression. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object EvaluateDocument(string specifier); + + /// + /// Loads and evaluates a document with the specified category. + /// + /// A string specifying the document to be loaded and evaluated. + /// An optional category for the requested document. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as an expression. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object EvaluateDocument(string specifier, DocumentCategory category); + + /// + /// Loads and evaluates a document with the specified category and context callback. + /// + /// A string specifying the document to be loaded and evaluated. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The result value. + /// + /// + /// In some script languages the distinction between statements and expressions is + /// significant but ambiguous for certain syntactic elements. This method always + /// interprets script code loaded from the specified document as an expression. + /// + /// + /// For information about the types of result values that script code can return, see + /// . + /// + /// + object EvaluateDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback); + + /// + /// Invokes a global function or procedure. + /// + /// The name of the global function or procedure to invoke. + /// Optional invocation arguments. + /// The return value if a function was invoked, an undefined value otherwise. + object Invoke(string funcName, params object[] args); + + /// + /// Gets a string representation of the script call stack. + /// + /// The script call stack formatted as a string. + /// + /// This method returns an empty string if the script engine is not executing script code. + /// The stack trace text format is defined by the script engine. + /// + string GetStackTrace(); + + /// + /// Interrupts script execution and causes the script engine to throw an exception. + /// + /// + /// This method can be called safely from any thread. + /// + void Interrupt(); + + /// + /// Performs garbage collection. + /// + /// True to perform exhaustive garbage collection, false to favor speed over completeness. + void CollectGarbage(bool exhaustive); + } +} diff --git a/Unity/Package/Runtime/IScriptEngine.cs.meta b/Unity/Package/Runtime/IScriptEngine.cs.meta new file mode 100644 index 000000000..04fcd84a3 --- /dev/null +++ b/Unity/Package/Runtime/IScriptEngine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9c29628d75058640b6d01f17f2c6581 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/IScriptEngineException.cs b/Unity/Package/Runtime/IScriptEngineException.cs new file mode 100644 index 000000000..673480b65 --- /dev/null +++ b/Unity/Package/Runtime/IScriptEngineException.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Defines common script engine exception properties. + /// + public interface IScriptEngineException + { + /// + /// Gets the error message. + /// + string Message { get; } + + /// + /// Gets an HRESULT error code if one is available, zero otherwise. + /// + int HResult { get; } + + /// + /// Gets the name associated with the script engine instance. + /// + string EngineName { get; } + + /// + /// Gets a detailed error message if one is available, null otherwise. + /// + string ErrorDetails { get; } + + /// + /// Gets a value that indicates whether the exception represents a fatal error. + /// + bool IsFatal { get; } + + /// + /// Gets a value that indicates whether script code execution had started before the current exception was thrown. + /// + bool ExecutionStarted { get; } + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified. + /// + dynamic ScriptException { get; } + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified, without engaging the dynamic infrastructure. + /// + object ScriptExceptionAsObject { get; } + + /// + /// Gets the host exception that caused the current exception to be thrown, or null if one was not specified. + /// + Exception InnerException { get; } + } +} diff --git a/Unity/Package/Runtime/IScriptEngineException.cs.meta b/Unity/Package/Runtime/IScriptEngineException.cs.meta new file mode 100644 index 000000000..778263858 --- /dev/null +++ b/Unity/Package/Runtime/IScriptEngineException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b166ec348357e145bcac0b423644bb0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/IScriptObject.cs b/Unity/Package/Runtime/IScriptObject.cs new file mode 100644 index 000000000..d28ac13ec --- /dev/null +++ b/Unity/Package/Runtime/IScriptObject.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a script object. + /// + public interface IScriptObject : IDisposable + { + /// + /// Gets the script engine that owns the object. + /// + ScriptEngine Engine { get; } + + /// + /// Gets the value of a named script object property. + /// + /// The name of the property to get. + /// Optional arguments for property retrieval. + /// The value of the specified property. + object GetProperty(string name, params object[] args); + + /// + /// Sets the value of a named script object property. + /// + /// The name of the property to set. + /// An array containing optional arguments and the new property value. + /// + /// The array must contain at least one element. The new + /// property value must be the last element of the array. + /// + void SetProperty(string name, params object[] args); + + /// + /// Removes a named script object property. + /// + /// The name of the property to remove. + /// True if the property was removed successfully, false otherwise. + bool DeleteProperty(string name); + + /// + /// Enumerates the script object's property names. + /// + IEnumerable PropertyNames { get; } + + /// + /// Gets or sets the value of a named script object property. + /// + /// The name of the property to get or set. + /// Optional arguments for property access. + /// The value of the specified property. + object this[string name, params object[] args] { get; set; } + + /// + /// Gets the value of an indexed script object property. + /// + /// The index of the property to get. + /// The value of the specified property. + object GetProperty(int index); + + /// + /// Sets the value of an indexed script object property. + /// + /// The index of the property to set. + /// The new property value. + void SetProperty(int index, object value); + + /// + /// Removes an indexed script object property. + /// + /// The index of the property to remove. + /// True if the property was removed successfully, false otherwise. + bool DeleteProperty(int index); + + /// + /// Enumerates the script object's property indices. + /// + IEnumerable PropertyIndices { get; } + + /// + /// Gets or sets the value of an indexed script object property. + /// + /// The index of the property to get or set. + /// The value of the specified property. + object this[int index] { get; set; } + + /// + /// Invokes the script object. + /// + /// True to invoke the object as a constructor, false otherwise. + /// Optional arguments for object invocation. + /// The invocation result value. + object Invoke(bool asConstructor, params object[] args); + + /// + /// Invokes a script object method. + /// + /// The name of the method to invoke. + /// Optional arguments for method invocation. + /// The invocation result value. + object InvokeMethod(string name, params object[] args); + + /// + /// Invokes the script object as a function. + /// + /// Optional arguments for object invocation. + /// The invocation result value. + object InvokeAsFunction(params object[] args); + } +} diff --git a/Unity/Package/Runtime/IScriptObject.cs.meta b/Unity/Package/Runtime/IScriptObject.cs.meta new file mode 100644 index 000000000..c89ccca46 --- /dev/null +++ b/Unity/Package/Runtime/IScriptObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4da61b5b05ce1054595796603d28aa9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/IScriptableObject.cs b/Unity/Package/Runtime/IScriptableObject.cs new file mode 100644 index 000000000..09faa76d9 --- /dev/null +++ b/Unity/Package/Runtime/IScriptableObject.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Defines a method to be called when a host object is exposed to script code. + /// + public interface IScriptableObject + { + /// + /// Notifies the host object that it has been exposed to script code. + /// + /// The script engine in which the host object was exposed. + /// + /// This method may be called more than once for a given host object. The object may be + /// exposed in multiple script engines or many times in one script engine. Implementers + /// should avoid expensive operations within this method, or cache the results of such + /// operations for efficient retrieval during subsequent invocations. + /// + void OnExposedToScriptCode(ScriptEngine engine); + } +} diff --git a/Unity/Package/Runtime/IScriptableObject.cs.meta b/Unity/Package/Runtime/IScriptableObject.cs.meta new file mode 100644 index 000000000..a34cc2253 --- /dev/null +++ b/Unity/Package/Runtime/IScriptableObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 352cf5d2fe474f84bacc13538c8d9d20 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ImmutableValueAttribute.cs b/Unity/Package/Runtime/ImmutableValueAttribute.cs new file mode 100644 index 000000000..2f3c7aedd --- /dev/null +++ b/Unity/Package/Runtime/ImmutableValueAttribute.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies that instances of the target struct are immutable. + /// + /// + /// When this attribute is applied to a struct, ClearScript exposes the same object reference + /// for all instances of the struct that satisfy equality comparison, giving script code the + /// ability to use native equality operators to compare the exposed objects. This behavior is + /// also enabled automatically for all enums, readonly structs, numeric types, + /// , , + /// , and . + /// + [AttributeUsage(AttributeTargets.Struct)] + public sealed class ImmutableValueAttribute : Attribute + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public ImmutableValueAttribute() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + } +} diff --git a/Unity/Package/Runtime/ImmutableValueAttribute.cs.meta b/Unity/Package/Runtime/ImmutableValueAttribute.cs.meta new file mode 100644 index 000000000..f48d67544 --- /dev/null +++ b/Unity/Package/Runtime/ImmutableValueAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec8fd648ea1afb449af1cefb73f8501c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Invocability.cs b/Unity/Package/Runtime/Invocability.cs new file mode 100644 index 000000000..beaf07c87 --- /dev/null +++ b/Unity/Package/Runtime/Invocability.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + internal enum Invocability + { + // IMPORTANT: maintain bitwise equivalence with native enum IHostObjectUtil::Invocability + None, + Delegate, + Dynamic, + DefaultProperty + } +} diff --git a/Unity/Package/Runtime/Invocability.cs.meta b/Unity/Package/Runtime/Invocability.cs.meta new file mode 100644 index 000000000..cfce378eb --- /dev/null +++ b/Unity/Package/Runtime/Invocability.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45a35a7b1a55ea046b6ea65a96cbc8a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript.meta b/Unity/Package/Runtime/JavaScript.meta new file mode 100644 index 000000000..74dc2b47b --- /dev/null +++ b/Unity/Package/Runtime/JavaScript.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd69bf483eb784e4093c247ada09b825 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs b/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs new file mode 100644 index 000000000..c8c19b8e9 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.JavaScript +{ + /// + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + public sealed class CommonJSLegacyModule + { + private readonly ScriptObject context; + private readonly Func initializeContext; + private ScriptObject initializedContext; + + /// + public CommonJSLegacyModule(string id, string uri, object exports, ScriptObject context, Func initializeContext) + { + this.context = context; + this.initializeContext = initializeContext; + + this.id = id; + this.uri = uri; + this.exports = exports; + } + + // ReSharper disable InconsistentNaming + + /// + public string id { get; } + + /// + public string uri { get; } + + /// + public object exports { get; set; } + + /// + public object meta => GetInitializedContext(); + + // ReSharper restore InconsistentNaming + + private ScriptObject GetInitializedContext() + { + return initializedContext ?? (initializedContext = initializeContext(context)); + } + } +} diff --git a/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs.meta b/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs.meta new file mode 100644 index 000000000..0ffc78bdd --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/CommonJSLegacyModule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ad114ac9f8bfb14286f72bafb1aae42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/CommonJSManager.cs b/Unity/Package/Runtime/JavaScript/CommonJSManager.cs new file mode 100644 index 000000000..27c6eafa1 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/CommonJSManager.cs @@ -0,0 +1,248 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.JavaScript +{ + internal sealed class CommonJSManager + { + private readonly ScriptEngine engine; + private readonly ScriptObject createModule; + private readonly List moduleCache = new List(); + private static readonly DocumentInfo createModuleInfo = new DocumentInfo("CommonJS-createModule [internal]"); + + public CommonJSManager(ScriptEngine engine) + { + this.engine = engine; + if (((IJavaScriptEngine)engine).BaseLanguageVersion >= 5) + { + createModule = (ScriptObject)engine.Evaluate(createModuleInfo, @" + (function (id, uri, hostInitialize, hostRequire, initializeContext) { + 'use strict'; + var module = {}, exports = {}, context; + Object.defineProperty(module, 'id', { value: id }); + if (uri) { + Object.defineProperty(module, 'uri', { value: uri }); + } + module.exports = exports; + Object.defineProperty(module, 'meta', { get: function () { + return context || (context = initializeContext({})); + }}); + hostInitialize(exports, function (moduleId) { + return hostRequire(moduleId); + }); + return module; + }).valueOf() + "); + } + else + { + createModule = (ScriptObject)engine.Evaluate(createModuleInfo, @" + (function (id, uri, hostInitialize, hostRequire, initializeContext, LegacyModule) { + 'use strict'; + var exports = {}; + hostInitialize(exports, function (moduleId) { + return hostRequire(moduleId); + }); + return new LegacyModule(id, uri, exports, {}, initializeContext); + }).valueOf() + "); + } + } + + public int ModuleCacheSize => moduleCache.Count; + + public Module GetOrCreateModule(UniqueDocumentInfo documentInfo, string code) + { + var codeDigest = code.GetDigest(); + + var cachedModule = GetCachedModule(documentInfo, codeDigest); + if (cachedModule != null) + { + return cachedModule; + } + + return CacheModule(new Module(this, engine, documentInfo, codeDigest, code)); + } + + public Module GetOrCreateModule(UniqueDocumentInfo documentInfo, UIntPtr codeDigest, Func evaluator) + { + var cachedModule = GetCachedModule(documentInfo, codeDigest); + if (cachedModule != null) + { + return cachedModule; + } + + return CacheModule(new Module(this, engine, documentInfo, codeDigest, evaluator)); + } + + private Module GetCachedModule(UniqueDocumentInfo documentInfo, UIntPtr codeDigest) + { + for (var index = 0; index < moduleCache.Count; index++) + { + var cachedModule = moduleCache[index]; + if ((cachedModule.DocumentInfo.UniqueId == documentInfo.UniqueId) && (cachedModule.CodeDigest == codeDigest)) + { + moduleCache.RemoveAt(index); + moduleCache.Insert(0, cachedModule); + return cachedModule; + } + } + + return null; + } + + private Module CacheModule(Module module) + { + var cachedModule = moduleCache.FirstOrDefault(testModule => (testModule.DocumentInfo.UniqueId == module.DocumentInfo.UniqueId) && (testModule.CodeDigest == module.CodeDigest)); + if (cachedModule != null) + { + return cachedModule; + } + + var maxModuleCacheSize = Math.Max(16, Convert.ToInt32(Math.Min(ModuleCategory.CommonJS.MaxCacheSize, int.MaxValue))); + while (moduleCache.Count >= maxModuleCacheSize) + { + moduleCache.RemoveAt(moduleCache.Count - 1); + } + + moduleCache.Insert(0, module); + return module; + } + + #region Nested type: Module + + public sealed class Module + { + private readonly CommonJSManager manager; + private readonly ScriptEngine engine; + + private object module; + private object exports; + private object require; + + private ScriptObject function; + private bool invoked; + + private const string codePrefix = "(function (module, exports, require) {\n"; + private const string codeSuffix = "\n}).valueOf()"; + + public Module(CommonJSManager manager, ScriptEngine engine, UniqueDocumentInfo documentInfo, UIntPtr codeDigest, string code) + : this(manager, engine, documentInfo, codeDigest, () => engine.ExecuteRaw(documentInfo, GetAugmentedCode(code), true)) + { + } + + public Module(CommonJSManager manager, ScriptEngine engine, UniqueDocumentInfo documentInfo, UIntPtr codeDigest, Func evaluator) + { + this.manager = manager; + this.engine = engine; + + DocumentInfo = documentInfo; + CodeDigest = codeDigest; + Evaluator = evaluator; + } + + public UniqueDocumentInfo DocumentInfo { get; } + + public UIntPtr CodeDigest { get; } + + public Func Evaluator { get; set; } + + public static string GetAugmentedCode(string code) + { + return codePrefix + code + codeSuffix; + } + + public object Process() => Process(out _); + + public object Process(out object marshaledExports) + { + if (module == null) + { + var id = (DocumentInfo.Uri != null) ? DocumentInfo.Uri.AbsoluteUri : DocumentInfo.UniqueName; + var uri = (DocumentInfo.Uri != null) ? id : null; + Action hostInitialize = Initialize; + Func hostRequire = Require; + Func initializeContext = InitializeContext; + module = manager.createModule.Invoke(false, id, uri, hostInitialize, hostRequire, initializeContext, typeof(CommonJSLegacyModule).ToHostType(engine)); + } + + if (function == null) + { + function = (ScriptObject)engine.MarshalToHost(engine.ScriptInvoke(() => Evaluator()), false); + } + + object result; + if (invoked) + { + result = Undefined.Value; + } + else + { + invoked = true; + result = function.Invoke(false, module, exports, require); + exports = (module is CommonJSLegacyModule legacyModule) ? legacyModule.exports : ((ScriptObject)module).GetProperty("exports"); + } + + marshaledExports = engine.MarshalToScript(exports); + return result; + } + + private void Initialize(object scriptExports, object scriptRequire) + { + exports = scriptExports; + require = scriptRequire; + } + + private object Require(string specifier) + { + var document = engine.DocumentSettings.LoadDocument(DocumentInfo.Info, specifier, ModuleCategory.CommonJS, null); + + if (document.Info.Category == ModuleCategory.CommonJS) + { + var code = document.GetTextContents(); + if (engine.FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + var target = manager.GetOrCreateModule(document.Info.MakeUnique(engine), code); + target.Process(); + + return target.exports; + } + + if (document.Info.Category == DocumentCategory.Json) + { + return ((IJavaScriptEngine)engine).JsonModuleManager.GetOrCreateModule(document.Info.MakeUnique(engine), document.GetTextContents()).Result; + } + + var uri = document.Info.Uri; + var name = (uri != null) ? (uri.IsFile ? uri.LocalPath : uri.AbsoluteUri) : document.Info.Name; + throw new FileLoadException($"Unsupported document category '{document.Info.Category}'", name); + } + + private ScriptObject InitializeContext(ScriptObject context) + { + var callback = DocumentInfo.ContextCallback ?? engine.DocumentSettings.ContextCallback; + var properties = callback?.Invoke(DocumentInfo.Info); + if (properties != null) + { + foreach (var pair in properties) + { + context.SetProperty(pair.Key, pair.Value); + } + } + + return context; + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/JavaScript/CommonJSManager.cs.meta b/Unity/Package/Runtime/JavaScript/CommonJSManager.cs.meta new file mode 100644 index 000000000..b4570e623 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/CommonJSManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2bc228f38fdb0a448dc02fb03694803 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs b/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs new file mode 100644 index 000000000..a4ec13f02 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Represents a JavaScript + /// ArrayBuffer. + /// + public interface IArrayBuffer : IJavaScriptObject + { + /// + /// Gets the size of the ArrayBuffer in bytes. + /// + ulong Size { get; } + + /// + /// Creates a byte array containing a copy of the ArrayBuffer's contents. + /// + /// A new byte array containing a copy of the ArrayBuffer's contents. + byte[] GetBytes(); + + /// + /// Copies bytes from the ArrayBuffer into the specified byte array. + /// + /// The offset within the ArrayBuffer of the first byte to copy. + /// The maximum number of bytes to copy. + /// The byte array into which to copy the bytes. + /// The index within at which to store the first copied byte. + /// The number of bytes copied. + ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex); + + /// + /// Copies bytes from the specified byte array into the ArrayBuffer. + /// + /// The byte array from which to copy the bytes. + /// The index within of the first byte to copy. + /// The maximum number of bytes to copy. + /// The offset within the ArrayBuffer at which to store the first copied byte. + /// The number of bytes copied. + ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset); + + /// + /// Invokes a delegate that returns no value, giving it direct access to the ArrayBuffer's contents. + /// + /// The delegate to invoke. + /// + /// This method invokes the specified delegate, passing in the memory address of the + /// ArrayBuffer's contents. This memory address is valid only while the delegate is + /// executing. The delegate must not access memory outside the ArrayBuffer's range. + /// + void InvokeWithDirectAccess(Action action); + + /// + /// Invokes a delegate that returns a value, giving it direct access to the ArrayBuffer's contents. + /// + /// The delegate's return type. + /// The delegate to invoke. + /// The delegate's return value. + /// + /// This method invokes the specified delegate, passing in the memory address of the + /// ArrayBuffer's contents. This memory address is valid only while the delegate is + /// executing. The delegate must not access memory outside the ArrayBuffer's range. + /// + T InvokeWithDirectAccess(Func func); + } +} diff --git a/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs.meta b/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs.meta new file mode 100644 index 000000000..4c3d504f1 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IArrayBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 291fdcf9f2dca504eadb8254669930d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs b/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs new file mode 100644 index 000000000..311b016e3 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Defines properties and methods common to all + /// ArrayBuffer + /// views. + /// + public interface IArrayBufferView : IJavaScriptObject + { + /// + /// Gets view's underlying ArrayBuffer. + /// + IArrayBuffer ArrayBuffer { get; } + + /// + /// Gets the view's offset within the underlying ArrayBuffer. + /// + ulong Offset { get; } + + /// + /// Gets the view's size in bytes. + /// + ulong Size { get; } + + /// + /// Creates a byte array containing a copy of the view's contents. + /// + /// A new byte array containing a copy of the view's contents. + byte[] GetBytes(); + + /// + /// Copies bytes from the view into the specified byte array. + /// + /// The offset within the view of the first byte to copy. + /// The maximum number of bytes to copy. + /// The byte array into which to copy the bytes. + /// The index within at which to store the first copied byte. + /// The number of bytes copied. + ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex); + + /// + /// Copies bytes from the specified byte array into the view. + /// + /// The byte array from which to copy the bytes. + /// The index within of the first byte to copy. + /// The maximum number of bytes to copy. + /// The offset within the view at which to store the first copied byte. + /// The number of bytes copied. + ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset); + + /// + /// Invokes a delegate that returns no value, giving it direct access to the view's contents. + /// + /// The delegate to invoke. + /// + /// This method invokes the specified delegate, passing in the memory address of the view's + /// contents. This memory address is valid only while the delegate is executing. The + /// delegate must not access memory outside the view's range. + /// + void InvokeWithDirectAccess(Action action); + + /// + /// Invokes a delegate that returns a value, giving it direct access to the view's contents. + /// + /// The delegate's return type. + /// The delegate to invoke. + /// The delegate's return value. + /// + /// This method invokes the specified delegate, passing in the memory address of the view's + /// contents. This memory address is valid only while the delegate is executing. The + /// delegate must not access memory outside the view's range. + /// + T InvokeWithDirectAccess(Func func); + } +} diff --git a/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs.meta b/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs.meta new file mode 100644 index 000000000..094da1376 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IArrayBufferView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc85f6ce322230c41a1a6d12ff05ae09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IDataView.cs b/Unity/Package/Runtime/JavaScript/IDataView.cs new file mode 100644 index 000000000..a15cfa7ff --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IDataView.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Represents a JavaScript + /// DataView. + /// + public interface IDataView : IArrayBufferView + { + } +} diff --git a/Unity/Package/Runtime/JavaScript/IDataView.cs.meta b/Unity/Package/Runtime/JavaScript/IDataView.cs.meta new file mode 100644 index 000000000..de137ff74 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IDataView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ba2f08004c3591429d5131f23ed6fa2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs new file mode 100644 index 000000000..227fcc555 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.JavaScript +{ + internal partial interface IJavaScriptEngine + { + object CreatePromiseForValueTask(ValueTask valueTask); + object CreatePromiseForValueTask(ValueTask valueTask); + } +} diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs.meta b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs.meta new file mode 100644 index 000000000..b1608b49c --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7708d9bbc5c832949920cc4d25518397 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs new file mode 100644 index 000000000..c7d2f9aba --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.JavaScript +{ + // ReSharper disable once PartialTypeWithSinglePart + internal partial interface IJavaScriptEngine : IScriptEngine + { + uint BaseLanguageVersion { get; } + + CommonJSManager CommonJSManager { get; } + JsonModuleManager JsonModuleManager { get; } + + object CreatePromiseForTask(Task task); + object CreatePromiseForTask(Task task); + + Task CreateTaskForPromise(ScriptObject promise); + } +} diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs.meta b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs.meta new file mode 100644 index 000000000..bcb378c8c --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptEngine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a81e69f38e864a48a748a684bd671aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs b/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs new file mode 100644 index 000000000..b30a4f3ee --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Represents a JavaScript object. + /// + public interface IJavaScriptObject : IScriptObject + { + /// + /// Gets the JavaScript object kind. + /// + JavaScriptObjectKind Kind { get; } + + /// + /// Gets the JavaScript object's attributes. + /// + JavaScriptObjectFlags Flags { get; } + } +} diff --git a/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs.meta b/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs.meta new file mode 100644 index 000000000..48f7c97f2 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/IJavaScriptObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f59edd8287dd6e14e90f0322fb2e099c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/ITypedArray.cs b/Unity/Package/Runtime/JavaScript/ITypedArray.cs new file mode 100644 index 000000000..3153fbc9d --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/ITypedArray.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Defines properties and methods common to all JavaScript + /// typed arrays. + /// + public interface ITypedArray : IArrayBufferView + { + /// + /// Gets the typed array's length. + /// + ulong Length { get; } + } + + /// + /// Represents a JavaScript typed array. + /// + /// The typed array's element type. + /// + /// + /// The following table lists the specific interfaces implemented by JavaScript typed arrays: + /// + /// + /// + /// + /// Typed Array + /// Interface(s) (C#) + /// + /// + /// Uint8Array + /// ITypedArray<byte> + /// + /// + /// Uint8ClampedArray + /// ITypedArray<byte> + /// + /// + /// Int8Array + /// ITypedArray<sbyte> + /// + /// + /// Uint16Array + /// ITypedArray<ushort> and ITypedArray<char> + /// + /// + /// Int16Array + /// ITypedArray<short> + /// + /// + /// Uint32Array + /// ITypedArray<uint> + /// + /// + /// Int32Array + /// ITypedArray<int> + /// + /// + /// BigUint64Array + /// ITypedArray<ulong> + /// + /// + /// BigInt64Array + /// ITypedArray<long> + /// + /// + /// Float32Array + /// ITypedArray<float> + /// + /// + /// Float64Array + /// ITypedArray<double> + /// + /// + /// + /// + public interface ITypedArray : ITypedArray + { + /// + /// Creates an array containing a copy of the typed array's contents. + /// + /// A new array containing a copy of the typed array's contents. + T[] ToArray(); + + /// + /// Copies elements from the typed array into the specified array. + /// + /// The index within the typed array of the first element to copy. + /// The maximum number of elements to copy. + /// The array into which to copy the elements. + /// The index within at which to store the first copied element. + /// The number of elements copied. + ulong Read(ulong index, ulong length, T[] destination, ulong destinationIndex); + + /// + /// Copies elements from the specified array into the typed array. + /// + /// The array from which to copy the elements. + /// The index within of the first element to copy. + /// The maximum number of elements to copy. + /// The index within the typed array at which to store the first copied element. + /// The number of elements copied. + ulong Write(T[] source, ulong sourceIndex, ulong length, ulong index); + } +} diff --git a/Unity/Package/Runtime/JavaScript/ITypedArray.cs.meta b/Unity/Package/Runtime/JavaScript/ITypedArray.cs.meta new file mode 100644 index 000000000..2891db934 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/ITypedArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22973e85f5350e9419034c627f52d21e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs new file mode 100644 index 000000000..0aaa4412f --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.JavaScript +{ + public static partial class JavaScriptExtensions + { + /// + /// Converts a instance to a + /// promise + /// for use with script code currently running on the calling thread. + /// + /// The task's result type. + /// The task to convert to a promise. + /// A promise that represents the task's asynchronous operation. + /// + /// This method is not available on .NET Framework or Universal Windows Platform (UWP). + /// + public static object ToPromise(this ValueTask valueTask) + { + return valueTask.ToPromise(ScriptEngine.Current); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code running in the specified script engine. + /// + /// The task's result type. + /// The task to convert to a promise. + /// The script engine in which the promise will be used. + /// A promise that represents the task's asynchronous operation. + /// + /// This method is not available on .NET Framework or Universal Windows Platform (UWP). + /// + public static object ToPromise(this ValueTask valueTask, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(valueTask, nameof(valueTask)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + + var javaScriptEngine = engine as IJavaScriptEngine; + if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6)) + { + throw new NotSupportedException("The script engine does not support promises"); + } + + return javaScriptEngine.CreatePromiseForValueTask(valueTask); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code currently running on the calling thread. + /// + /// The task to convert to a promise. + /// A promise that represents the task's asynchronous operation. + /// + /// This method is not available on .NET Framework or Universal Windows Platform (UWP). + /// + public static object ToPromise(this ValueTask valueTask) + { + return valueTask.ToPromise(ScriptEngine.Current); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code running in the specified script engine. + /// + /// The task to convert to a promise. + /// The script engine in which the promise will be used. + /// A promise that represents the task's asynchronous operation. + /// + /// This method is not available on .NET Framework or Universal Windows Platform (UWP). + /// + public static object ToPromise(this ValueTask valueTask, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(valueTask, nameof(valueTask)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + + var javaScriptEngine = engine as IJavaScriptEngine; + if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6)) + { + throw new NotSupportedException("The script engine does not support promises"); + } + + return javaScriptEngine.CreatePromiseForValueTask(valueTask); + } + + /// + /// Supports managed asynchronous iteration over an + /// async-iterable + /// script object. + /// + /// An async-iterable script object (see remarks). + /// An IAsyncEnumerator<Object> implementation that supports managed asynchronous iteration over . + /// + /// If the argument implements IAsyncEnumerator<Object>, this method returns it as is. + /// + public static IAsyncEnumerable ToAsyncEnumerable(this object asyncIterable) + { + MiscHelpers.VerifyNonNullArgument(asyncIterable, nameof(asyncIterable)); + return asyncIterable as IAsyncEnumerable ?? asyncIterable.ToAsyncEnumerableInternal(); + } + + private static async IAsyncEnumerable ToAsyncEnumerableInternal(this object asyncIterable) + { + if (asyncIterable is IEnumerable objectEnumerable) + { + foreach (var item in objectEnumerable) + { + yield return item; + } + } + else if (asyncIterable is ScriptObject scriptObject) + { + if (scriptObject.Engine is IJavaScriptEngine javaScriptEngine && (javaScriptEngine.BaseLanguageVersion >= 6)) + { + var engineInternal = (ScriptObject)javaScriptEngine.Global["EngineInternal"]; + if (engineInternal.InvokeMethod("getAsyncIterator", scriptObject) is ScriptObject asyncIterator) + { + while (await asyncIterator.InvokeMethod("next").ToTask().ConfigureAwait(false) is ScriptObject result && !Equals(result["done"], true)) + { + yield return result["value"]; + } + } + else if (engineInternal.InvokeMethod("getIterator", scriptObject) is ScriptObject iterator) + { + while (iterator.InvokeMethod("next") is ScriptObject result && !Equals(result["done"], true)) + { + yield return result["value"]; + } + } + else + { + throw new ArgumentException("The object is not async-iterable", nameof(asyncIterable)); + } + } + else + { + throw new NotSupportedException("The script engine does not support async iteration"); + } + } + else if (asyncIterable is IEnumerable enumerable) + { + foreach (var item in enumerable) + { + yield return item; + } + } + else + { + throw new ArgumentException("The object is not async-iterable", nameof(asyncIterable)); + } + } + } +} diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs.meta b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs.meta new file mode 100644 index 000000000..71abd0785 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a3e195c7d3002346b81b898eb2b4de5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs new file mode 100644 index 000000000..862d079e6 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs @@ -0,0 +1,184 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.JavaScript +{ + // ReSharper disable once PartialTypeWithSinglePart + + /// + /// Defines extension methods for use with JavaScript engines. + /// + public static partial class JavaScriptExtensions + { + /// + /// Converts a instance to a + /// promise + /// for use with script code currently running on the calling thread. + /// + /// The task's result type. + /// The task to convert to a promise. + /// A promise that represents the task's asynchronous operation. + public static object ToPromise(this Task task) + { + return task.ToPromise(ScriptEngine.Current); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code running in the specified script engine. + /// + /// The task's result type. + /// The task to convert to a promise. + /// The script engine in which the promise will be used. + /// A promise that represents the task's asynchronous operation. + public static object ToPromise(this Task task, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(task, nameof(task)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + + var javaScriptEngine = engine as IJavaScriptEngine; + if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6)) + { + throw new NotSupportedException("The script engine does not support promises"); + } + + return javaScriptEngine.CreatePromiseForTask(task); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code currently running on the calling thread. + /// + /// The task to convert to a promise. + /// A promise that represents the task's asynchronous operation. + public static object ToPromise(this Task task) + { + return task.ToPromise(ScriptEngine.Current); + } + + /// + /// Converts a instance to a + /// promise + /// for use with script code running in the specified script engine. + /// + /// The task to convert to a promise. + /// The script engine in which the promise will be used. + /// A promise that represents the task's asynchronous operation. + public static object ToPromise(this Task task, ScriptEngine engine) + { + MiscHelpers.VerifyNonNullArgument(task, nameof(task)); + MiscHelpers.VerifyNonNullArgument(engine, nameof(engine)); + + var javaScriptEngine = engine as IJavaScriptEngine; + if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6)) + { + throw new NotSupportedException("The script engine does not support promises"); + } + + return javaScriptEngine.CreatePromiseForTask(task); + } + + /// + /// Converts a + /// promise + /// to a Task<Object> instance. + /// + /// The promise to convert to a task (see remarks). + /// A task that represents the promise's asynchronous operation. + /// + /// If the argument is a Task<Object> instance, + /// this method returns it as is. + /// + public static Task ToTask(this object promise) + { + MiscHelpers.VerifyNonNullArgument(promise, nameof(promise)); + return promise as Task ?? promise.ToTaskInternal(); + } + + /// + /// Supports managed iteration over an + /// iterable + /// script object. + /// + /// An iterable script object (see remarks). + /// An IEnumerable<Object> implementation that supports managed iteration over . + /// + /// If the argument implements + /// IEnumerable<Object>, this method + /// returns it as is. + /// + public static IEnumerable ToEnumerable(this object iterable) + { + // WARNING: The IEnumerable test below is a bit dicey, as most IEnumerable + // implementations support IEnumerable via covariance. The desired behavior + // here is for that test to fail for IDictionary, as V8 script objects + // now support that interface. Luckily, that test does fail, but only because + // KeyValuePair is a struct, so covariance doesn't apply. + + MiscHelpers.VerifyNonNullArgument(iterable, nameof(iterable)); + return iterable as IEnumerable ?? iterable.ToEnumerableInternal(); + } + + private static Task ToTaskInternal(this object promise) + { + var scriptObject = promise as ScriptObject; + if (scriptObject == null) + { + throw new ArgumentException("The object is not a promise", nameof(promise)); + } + + var javaScriptEngine = scriptObject.Engine as IJavaScriptEngine; + if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6)) + { + throw new NotSupportedException("The script engine does not support promises"); + } + + return javaScriptEngine.CreateTaskForPromise(scriptObject); + } + + private static IEnumerable ToEnumerableInternal(this object iterable) + { + if (iterable is ScriptObject scriptObject) + { + if (scriptObject.Engine is IJavaScriptEngine javaScriptEngine && (javaScriptEngine.BaseLanguageVersion >= 6)) + { + var engineInternal = (ScriptObject)javaScriptEngine.Global["EngineInternal"]; + if (engineInternal.InvokeMethod("getIterator", scriptObject) is ScriptObject iterator) + { + while (iterator.InvokeMethod("next") is ScriptObject result && !Equals(result["done"], true)) + { + yield return result["value"]; + } + } + else + { + throw new ArgumentException("The object is not iterable", nameof(iterable)); + } + } + else + { + throw new NotSupportedException("The script engine does not support iteration"); + } + } + else if (iterable is IEnumerable enumerable) + { + foreach (var item in enumerable) + { + yield return item; + } + } + else + { + throw new ArgumentException("The object is not iterable", nameof(iterable)); + } + } + } +} diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs.meta b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs.meta new file mode 100644 index 000000000..a446026c2 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d51d565056be6c347bcf9acfed54ec74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs b/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs new file mode 100644 index 000000000..d5363fbfe --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Defines JavaScript object attributes. + /// + [Flags] + public enum JavaScriptObjectFlags + { + /// + /// Indicates that no attributes are present. + /// + None = 0, + + /// + /// Indicates that the object is an + /// ArrayBuffer, + /// DataView, + /// or + /// typed array whose contents reside in shared memory. + /// + Shared = 0x00000001, + + /// + /// Indicates that the object is an + /// async function + /// or + /// async iterator. + /// + Async = 0x00000002, + + /// + /// Indicates that the object is a + /// generator function + /// or + /// async generator function. + /// + Generator = 0x00000004 + } +} diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs.meta b/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs.meta new file mode 100644 index 000000000..e2f6036f9 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptObjectFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c352e60b043e8594087b4ead5d0ffae1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs b/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs new file mode 100644 index 000000000..0d92d5841 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Defines JavaScript object kinds. + /// + public enum JavaScriptObjectKind + { + /// + /// Indicates that the object is generic or of an unknown kind. + /// + Unknown, + + /// + /// Indicates that the object is a + /// function. + /// + Function, + + /// + /// Indicates that the object is an + /// iterator. + /// + Iterator, + + /// + /// Indicates that the object is a + /// promise. + /// + Promise, + + /// + /// Indicates that the object is an + /// array + /// and implements + /// IList. + /// + Array, + + /// + /// Indicates that the object is an + /// ArrayBuffer + /// and implements . + /// + ArrayBuffer, + + /// + /// Indicates that the object is a + /// DataView + /// and implements . + /// + DataView, + + /// + /// Indicates that the object is a + /// typed array + /// and implements . + /// + TypedArray + } +} diff --git a/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs.meta b/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs.meta new file mode 100644 index 000000000..75e0fd39f --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JavaScriptObjectKind.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6aa3b05bddfa487449586d031e62ead9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs b/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs new file mode 100644 index 000000000..1c1138393 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.JavaScript +{ + internal sealed class JsonModuleManager + { + private readonly ScriptEngine engine; + private readonly List moduleCache = new List(); + + public JsonModuleManager(ScriptEngine engine) + { + this.engine = engine; + } + + public int ModuleCacheSize => moduleCache.Count; + + public Module GetOrCreateModule(UniqueDocumentInfo documentInfo, string json) + { + var jsonDigest = json.GetDigest(); + + var cachedModule = GetCachedModule(documentInfo, jsonDigest); + if (cachedModule != null) + { + return cachedModule; + } + + return CacheModule(new Module(engine, documentInfo, jsonDigest, json)); + } + + private Module GetCachedModule(UniqueDocumentInfo documentInfo, UIntPtr jsonDigest) + { + for (var index = 0; index < moduleCache.Count; index++) + { + var cachedModule = moduleCache[index]; + if ((cachedModule.DocumentInfo.UniqueId == documentInfo.UniqueId) && (cachedModule.JsonDigest == jsonDigest)) + { + moduleCache.RemoveAt(index); + moduleCache.Insert(0, cachedModule); + return cachedModule; + } + } + + return null; + } + + private Module CacheModule(Module module) + { + var cachedModule = moduleCache.FirstOrDefault(testModule => (testModule.DocumentInfo.UniqueId == module.DocumentInfo.UniqueId) && (testModule.JsonDigest == module.JsonDigest)); + if (cachedModule != null) + { + return cachedModule; + } + + var maxModuleCacheSize = Math.Max(16, Convert.ToInt32(Math.Min(DocumentCategory.Json.MaxCacheSize, int.MaxValue))); + while (moduleCache.Count >= maxModuleCacheSize) + { + moduleCache.RemoveAt(moduleCache.Count - 1); + } + + moduleCache.Insert(0, module); + return module; + } + + #region Nested type: Module + + public sealed class Module + { + private readonly ScriptEngine engine; + private readonly string json; + + private bool parsed; + private object result; + + public Module(ScriptEngine engine, UniqueDocumentInfo documentInfo, UIntPtr jsonDigest, string json) + { + this.engine = engine; + this.json = json; + + DocumentInfo = documentInfo; + JsonDigest = jsonDigest; + } + + public UniqueDocumentInfo DocumentInfo { get; } + + public UIntPtr JsonDigest { get; } + + public object Result + { + get + { + if (!parsed) + { + parsed = true; + result = ((ScriptObject)engine.Global.GetProperty("EngineInternal")).InvokeMethod("parseJson", json); + } + + return result; + } + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs.meta b/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs.meta new file mode 100644 index 000000000..cfe0bac3e --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/JsonModuleManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 563d14dfa61d6234a88503e4196f2b91 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/JavaScript/ModuleCategory.cs b/Unity/Package/Runtime/JavaScript/ModuleCategory.cs new file mode 100644 index 000000000..e632ad88e --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/ModuleCategory.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.JavaScript +{ + /// + /// Defines document categories for JavaScript modules. + /// + public static class ModuleCategory + { + /// + /// Gets the document category for standard ECMAScript 6 modules. + /// + public static DocumentCategory Standard => StandardModule.Instance; + + /// + /// Gets the document category for CommonJS modules. + /// + public static DocumentCategory CommonJS => CommonJSModule.Instance; + + #region Nested type: StandardModule + + private sealed class StandardModule : DocumentCategory + { + public static readonly StandardModule Instance = new StandardModule(); + + private StandardModule() + { + } + + #region DocumentCategory overrides + + internal override DocumentKind Kind => DocumentKind.JavaScriptModule; + + internal override string DefaultName => "Module"; + + #endregion + + #region Object overrides + + public override string ToString() + { + return "ECMAScript Module"; + } + + #endregion + } + + #endregion + + #region Nested type: CommonJSModule + + private sealed class CommonJSModule : DocumentCategory + { + public static readonly CommonJSModule Instance = new CommonJSModule(); + + private CommonJSModule() + { + } + + #region DocumentCategory overrides + + internal override DocumentKind Kind => DocumentKind.CommonJSModule; + + internal override string DefaultName => "Module"; + + #endregion + + #region Object overrides + + public override string ToString() + { + return "CommonJS Module"; + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/JavaScript/ModuleCategory.cs.meta b/Unity/Package/Runtime/JavaScript/ModuleCategory.cs.meta new file mode 100644 index 000000000..85dec2a80 --- /dev/null +++ b/Unity/Package/Runtime/JavaScript/ModuleCategory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08b65bbf1eeb7a444bf5285c024301f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs b/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs new file mode 100644 index 000000000..6719ac21b --- /dev/null +++ b/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies that script code is to have no access to type members by default. + /// + /// + /// This attribute is applicable to classes, enums, interfaces, structs, and assemblies. Use + /// , , or + /// to override it for individual type members. Note that + /// it has no effect on the method binding algorithm. If a script-based call is bound to a + /// method that is blocked by this attribute, it will be rejected even if an overload exists + /// that could receive the call. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Assembly)] + public sealed class NoDefaultScriptAccessAttribute : DefaultScriptUsageAttribute + { + /// + /// Initializes a new instance. + /// + public NoDefaultScriptAccessAttribute() + : base(ScriptAccess.None) + { + } + } +} diff --git a/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs.meta b/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs.meta new file mode 100644 index 000000000..f0ea7bf0e --- /dev/null +++ b/Unity/Package/Runtime/NoDefaultScriptAccessAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d9ae2c2f052cdd469d5f8dc7c1efbce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/NoScriptAccessAttribute.cs b/Unity/Package/Runtime/NoScriptAccessAttribute.cs new file mode 100644 index 000000000..65bee1744 --- /dev/null +++ b/Unity/Package/Runtime/NoScriptAccessAttribute.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies that script code is to have no access to the target type member. + /// + /// + /// This attribute is applicable to events, fields, methods, properties, and nested types. Note + /// that it has no effect on the method binding algorithm. If a script-based call is bound to a + /// method that is blocked by this attribute, it will be rejected even if an overload exists + /// that could receive the call. + /// + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct)] + public sealed class NoScriptAccessAttribute : ScriptUsageAttribute + { + /// + /// Initializes a new instance. + /// + public NoScriptAccessAttribute() + : base(ScriptAccess.None) + { + } + } +} diff --git a/Unity/Package/Runtime/NoScriptAccessAttribute.cs.meta b/Unity/Package/Runtime/NoScriptAccessAttribute.cs.meta new file mode 100644 index 000000000..d575e43d6 --- /dev/null +++ b/Unity/Package/Runtime/NoScriptAccessAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3bf36b33655ec14fb9a1284f9063234 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Properties.meta b/Unity/Package/Runtime/Properties.meta new file mode 100644 index 000000000..cc1f855cd --- /dev/null +++ b/Unity/Package/Runtime/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ba24c139ef2cbf6408a7a158714fd5aa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs b/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs new file mode 100644 index 000000000..a67a56c90 --- /dev/null +++ b/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + + + + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ClearScript Core Library")] +[assembly: AssemblyProduct("ClearScript")] +[assembly: AssemblyCopyright("(c) Microsoft Corporation")] +[assembly: InternalsVisibleTo("Decentraland.ClearScript.Tests")] + +[assembly: ComVisible(false)] +[assembly: AssemblyVersion("7.4.5")] +[assembly: AssemblyFileVersion("7.4.5")] +[assembly: AssemblyInformationalVersion("7.4.5")] + +namespace Microsoft.ClearScript.Properties +{ + internal static class ClearScriptVersion + { + public const string Triad = "7.4.5"; + public const string Informational = "7.4.5"; + } +} diff --git a/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs.meta b/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs.meta new file mode 100644 index 000000000..7a04441bb --- /dev/null +++ b/Unity/Package/Runtime/Properties/AssemblyInfo.Core.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0717792bb430aa0418a649128e49691e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/PropertyBag.cs b/Unity/Package/Runtime/PropertyBag.cs new file mode 100644 index 000000000..bd8068bdb --- /dev/null +++ b/Unity/Package/Runtime/PropertyBag.cs @@ -0,0 +1,405 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Represents a scriptable collection of named properties. + /// + /// + /// If an object that implements this interface is added to a script engine (see + /// AddHostObject), script code + /// will be able to access the properties stored in the collection as if they were members of + /// the object itself, using the script language's native syntax for member access. No + /// other members of the object will be accessible. This interface also allows objects to + /// implement dynamic properties for script languages that support them. + /// + public interface IPropertyBag : IDictionary + { + } + + /// + /// Provides a default implementation. + /// + public class PropertyBag : IPropertyBag, INotifyPropertyChanged, IScriptableObject + { + #region data + + private readonly IDictionary dictionary; + private readonly bool isReadOnly; + private readonly ConcurrentWeakSet engineSet = new ConcurrentWeakSet(); + + #endregion + + #region constructors + + /// + /// Initializes a new writable with the default property name comparer. + /// + public PropertyBag() + : this(false) + { + } + + /// + /// Initializes a new with the default property name comparer. + /// + /// True to make the read-only, false to make it writable. + /// + /// The host can modify a read-only by calling + /// SetPropertyNoCheck, + /// RemovePropertyNoCheck, or + /// ClearNoCheck. + /// + public PropertyBag(bool isReadOnly) + : this(isReadOnly, null) + { + } + + /// + /// Initializes a new writable . + /// + /// The comparer to use for property names, or null to use the default string comparer. + public PropertyBag(IEqualityComparer comparer) + : this(false, comparer) + { + } + + /// + /// Initializes a new . + /// + /// True to make the read-only, false to make it writable. + /// The comparer to use for property names, or null to use the default string comparer. + public PropertyBag(bool isReadOnly, IEqualityComparer comparer) + : this(isReadOnly, comparer, new Dictionary(comparer ?? EqualityComparer.Default)) + { + } + + internal PropertyBag(bool isReadOnly, IEqualityComparer comparer, IDictionary dictionary) + { + this.dictionary = dictionary; + this.isReadOnly = isReadOnly; + Comparer = comparer; + } + + #endregion + + #region public members + + /// + /// Gets the property name comparer for the . + /// + public IEqualityComparer Comparer { get; } + + /// + /// Sets a property value without checking whether the is read-only. + /// + /// The name of the property to set. + /// The property value. + /// + /// This operation is never exposed to script code. + /// + public void SetPropertyNoCheck(string name, object value) + { + dictionary[name] = value; + NotifyPropertyChanged(name); + NotifyExposedToScriptCode(value); + } + + /// + /// Removes a property without checking whether the is read-only. + /// + /// The name of the property to remove. + /// True if the property was found and removed, false otherwise. + /// + /// This operation is never exposed to script code. + /// + public bool RemovePropertyNoCheck(string name) + { + if (dictionary.Remove(name)) + { + NotifyPropertyChanged(name); + return true; + } + + return false; + } + + /// + /// Removes all properties without checking whether the is read-only. + /// + /// + /// This operation is never exposed to script code. + /// + public void ClearNoCheck() + { + dictionary.Clear(); + NotifyPropertyChanged(null); + } + + #endregion + + #region internal members + + internal int EngineCount => engineSet.Count; + + private void CheckReadOnly() + { + if (isReadOnly) + { + throw new UnauthorizedAccessException("The object is read-only"); + } + } + + private void AddPropertyNoCheck(string name, object value) + { + dictionary.Add(name, value); + NotifyPropertyChanged(name); + NotifyExposedToScriptCode(value); + } + + private void NotifyPropertyChanged(string name) + { + var handler = PropertyChanged; + handler?.Invoke(this, new PropertyChangedEventArgs(name)); + } + + private void NotifyExposedToScriptCode(object value) + { + if (value is IScriptableObject scriptableObject) + { + engineSet.ForEach(scriptableObject.OnExposedToScriptCode); + } + } + + #endregion + + #region IEnumerable implementation + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member requires explicit implementation to resolve ambiguity.")] + IEnumerator IEnumerable.GetEnumerator() + { + return dictionary.GetEnumerator(); + } + + #endregion + + #region IEnumerable> implementation + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member requires explicit implementation to resolve ambiguity.")] + IEnumerator> IEnumerable>.GetEnumerator() + { + return dictionary.GetEnumerator(); + } + + #endregion + + #region ICollection> implementation + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + void ICollection>.Add(KeyValuePair item) + { + CheckReadOnly(); + SetPropertyNoCheck(item.Key, item.Value); + } + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + void ICollection>.Clear() + { + CheckReadOnly(); + ClearNoCheck(); + } + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + bool ICollection>.Contains(KeyValuePair item) + { + return dictionary.Contains(item); + } + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + dictionary.CopyTo(array, arrayIndex); + } + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + bool ICollection>.Remove(KeyValuePair item) + { + CheckReadOnly(); + if (dictionary.Remove(item)) + { + NotifyPropertyChanged(item.Key); + return true; + } + + return false; + } + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + int ICollection>.Count => dictionary.Count; + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + bool ICollection>.IsReadOnly => isReadOnly; + + #endregion + + #region IDictionary implementation + + /// + /// Determines whether the contains a property with the specified name. + /// + /// The name of the property to locate. + /// True if the contains a property with the specified name, false otherwise. + public bool ContainsKey(string key) + { + return dictionary.ContainsKey(key); + } + + /// + /// Adds a property to the . + /// + /// The name of the property to add. + /// The property value. + public void Add(string key, object value) + { + CheckReadOnly(); + AddPropertyNoCheck(key, value); + } + + /// + /// Removes a property from the . + /// + /// The name of the property to remove. + /// True if the property was successfully found and removed, false otherwise. + public bool Remove(string key) + { + CheckReadOnly(); + return RemovePropertyNoCheck(key); + } + + /// + /// Looks up a property value in the . + /// + /// The name of the property to locate. + /// The property value if the property was found, null otherwise. + /// True if the property was found, false otherwise. + public bool TryGetValue(string key, out object value) + { + return dictionary.TryGetValue(key, out value); + } + + /// + /// Gets or sets a property value in the . + /// + /// The name of the property to get or set. + /// The property value. + public object this[string key] + { + get => dictionary[key]; + + set + { + CheckReadOnly(); + SetPropertyNoCheck(key, value); + } + } + + /// + /// Gets a collection of property names from the . + /// + public ICollection Keys => dictionary.Keys; + + /// + /// Gets a collection of property values from the . + /// + public ICollection Values => dictionary.Values; + + #endregion + + #region INotifyPropertyChanged implementation + + /// + /// Occurs when a property is added or replaced, or when the collection is cleared. + /// + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + #region IScriptableObject implementation + + [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This member is not expected to be re-implemented in derived classes.")] + void IScriptableObject.OnExposedToScriptCode(ScriptEngine engine) + { + if ((engine != null) && engineSet.TryAdd(engine)) + { + foreach (var scriptableObject in Values.OfType()) + { + scriptableObject.OnExposedToScriptCode(engine); + } + } + } + + #endregion + } + + /// + /// Provides a thread-safe implementation. + /// + public class ConcurrentPropertyBag : PropertyBag + { + #region constructors + + /// + /// Initializes a new writable with the default property name comparer. + /// + public ConcurrentPropertyBag() + : this(false) + { + } + + /// + /// Initializes a new with the default property name comparer. + /// + /// True to make the read-only, false to make it writable. + /// + /// The host can modify a read-only by calling + /// SetPropertyNoCheck, + /// RemovePropertyNoCheck, or + /// ClearNoCheck. + /// + public ConcurrentPropertyBag(bool isReadOnly) + : this(isReadOnly, null) + { + } + + /// + /// Initializes a new writable . + /// + /// The comparer to use for property names, or null to use the default string comparer. + public ConcurrentPropertyBag(IEqualityComparer comparer) + : this(false, comparer) + { + } + + /// + /// Initializes a new . + /// + /// True to make the read-only, false to make it writable. + /// The comparer to use for property names, or null to use the default string comparer. + public ConcurrentPropertyBag(bool isReadOnly, IEqualityComparer comparer) + : base(isReadOnly, comparer, new ConcurrentDictionary(comparer ?? EqualityComparer.Default)) + { + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/PropertyBag.cs.meta b/Unity/Package/Runtime/PropertyBag.cs.meta new file mode 100644 index 000000000..fd5f654ad --- /dev/null +++ b/Unity/Package/Runtime/PropertyBag.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2951cd472b9550c49b3b005bc0df2290 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptAccess.cs b/Unity/Package/Runtime/ScriptAccess.cs new file mode 100644 index 000000000..1ed176b19 --- /dev/null +++ b/Unity/Package/Runtime/ScriptAccess.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Defines script access settings for type members. + /// + public enum ScriptAccess + { + /// + /// Specifies that script code is to have full access to the type member. This is the + /// default setting. + /// + Full, + + /// + /// Specifies that script code is to have read-only access to the type member. This setting + /// only affects fields and writable properties. + /// + ReadOnly, + + /// + /// Specifies that script code is to have no access to the type member. Note that this + /// setting has no effect on the method binding algorithm. If a script-based call is bound + /// to a method that is blocked by this setting, it will be rejected even if an overload + /// exists that could receive the call. + /// + None + } +} diff --git a/Unity/Package/Runtime/ScriptAccess.cs.meta b/Unity/Package/Runtime/ScriptAccess.cs.meta new file mode 100644 index 000000000..0e73d522c --- /dev/null +++ b/Unity/Package/Runtime/ScriptAccess.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 310ae05afb5e5c944a8deae0a4e23226 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptEngine.cs b/Unity/Package/Runtime/ScriptEngine.cs new file mode 100644 index 000000000..b4a75e37c --- /dev/null +++ b/Unity/Package/Runtime/ScriptEngine.cs @@ -0,0 +1,1238 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// Provides the base implementation for all script engines. + /// + public abstract class ScriptEngine : IScriptEngine, IHostContext + { + #region data + + private Type accessContext; + private ScriptAccess defaultAccess; + private bool enforceAnonymousTypeAccess; + private bool exposeHostObjectStaticMembers; + private CustomAttributeLoader customAttributeLoader; + + private DocumentSettings documentSettings; + private readonly DocumentSettings defaultDocumentSettings = new DocumentSettings(); + + private static readonly IUniqueNameManager nameManager = new UniqueNameManager(); + private static readonly object nullHostObjectProxy = new object(); + [ThreadStatic] private static ScriptEngine currentEngine; + + #endregion + + #region constructors + + /// + /// Initializes a new script engine instance. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + [Obsolete("Use ScriptEngine(string name, string fileNameExtensions) instead.")] + protected ScriptEngine(string name) + : this(name, null) + { + } + + /// + /// Initializes a new script engine instance with the specified list of supported file name extensions. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A semicolon-delimited list of supported file name extensions. + protected ScriptEngine(string name, string fileNameExtensions) + { + Name = nameManager.GetUniqueName(name, GetType().GetRootName()); + defaultDocumentSettings.FileNameExtensions = fileNameExtensions; + extensionMethodTable = realExtensionMethodTable = new ExtensionMethodTable(); + } + + #endregion + + #region public members + + /// + /// Gets the script engine that is invoking a host member on the current thread. + /// + /// + /// If multiple script engines are invoking host members on the current thread, this + /// property gets the one responsible for the most deeply nested invocation. If no script + /// engines are invoking host members on the current thread, this property returns + /// null. + /// + public static ScriptEngine Current => currentEngine; + + #endregion + + #region IScriptEngine implementation + + /// + public string Name { get; } + + /// + public abstract string FileNameExtension { get; } + + /// + public Type AccessContext + { + get => accessContext; + + set + { + accessContext = value; + OnAccessSettingsChanged(); + } + } + + /// + public ScriptAccess DefaultAccess + { + get => defaultAccess; + + set + { + defaultAccess = value; + OnAccessSettingsChanged(); + } + } + + /// + public bool EnforceAnonymousTypeAccess + { + get => enforceAnonymousTypeAccess; + + set + { + enforceAnonymousTypeAccess = value; + OnAccessSettingsChanged(); + } + } + + /// + public bool ExposeHostObjectStaticMembers + { + get => exposeHostObjectStaticMembers; + + set + { + exposeHostObjectStaticMembers = value; + OnAccessSettingsChanged(); + } + } + + /// + public bool DisableExtensionMethods + { + get => extensionMethodTable == emptyExtensionMethodTable; + + set + { + var newExtensionMethodTable = value ? emptyExtensionMethodTable : realExtensionMethodTable; + if (newExtensionMethodTable != extensionMethodTable) + { + ScriptInvoke(() => + { + if (newExtensionMethodTable != extensionMethodTable) + { + extensionMethodTable = newExtensionMethodTable; + ClearMethodBindCache(); + OnAccessSettingsChanged(); + } + }); + } + } + } + + /// + public bool FormatCode { get; set; } + + /// + public bool AllowReflection { get; set; } + + /// + public bool DisableTypeRestriction { get; set; } + + /// + public bool DisableListIndexTypeRestriction { get; set; } + + /// + public bool EnableNullResultWrapping { get; set; } + + /// + public bool DisableFloatNarrowing { get; set; } + + /// + public bool DisableDynamicBinding { get; set; } + + /// + public bool UseReflectionBindFallback { get; set; } + + /// + public bool EnableAutoHostVariables { get; set; } + + /// + public object UndefinedImportValue { get; set; } = Undefined.Value; + + /// + public object NullExportValue { get; set; } + + /// + public object VoidResultValue { get; set; } = VoidResult.Value; + + /// + public ContinuationCallback ContinuationCallback { get; set; } + + /// + public abstract dynamic Script { get; } + + /// + public abstract ScriptObject Global { get; } + + /// + public DocumentSettings DocumentSettings + { + get => documentSettings ?? defaultDocumentSettings; + set => documentSettings = value; + } + + /// + public CustomAttributeLoader CustomAttributeLoader + { + get => customAttributeLoader; + + set + { + customAttributeLoader = value; + OnAccessSettingsChanged(); + } + } + + /// + public object HostData { get; set; } + + /// + public void AddHostObject(string itemName, object target) + { + AddHostObject(itemName, HostItemFlags.None, target); + } + + /// + public void AddHostObject(string itemName, HostItemFlags flags, object target) + { + MiscHelpers.VerifyNonNullArgument(target, nameof(target)); + AddHostItem(itemName, flags, target); + } + + /// + public void AddRestrictedHostObject(string itemName, T target) + { + AddRestrictedHostObject(itemName, HostItemFlags.None, target); + } + + /// + public void AddRestrictedHostObject(string itemName, HostItemFlags flags, T target) + { + AddHostItem(itemName, flags, HostItem.Wrap(this, target, typeof(T))); + } + + /// + public void AddCOMObject(string itemName, string progID) + { + AddCOMObject(itemName, HostItemFlags.None, progID); + } + + /// + public void AddCOMObject(string itemName, string progID, string serverName) + { + AddCOMObject(itemName, HostItemFlags.None, progID, serverName); + } + + /// + public void AddCOMObject(string itemName, HostItemFlags flags, string progID) + { + AddCOMObject(itemName, flags, progID, null); + } + + /// + public void AddCOMObject(string itemName, HostItemFlags flags, string progID, string serverName) + { + AddHostItem(itemName, flags, MiscHelpers.CreateCOMObject(progID, serverName)); + } + + /// + public void AddCOMObject(string itemName, Guid clsid) + { + AddCOMObject(itemName, HostItemFlags.None, clsid); + } + + /// + public void AddCOMObject(string itemName, Guid clsid, string serverName) + { + AddCOMObject(itemName, HostItemFlags.None, clsid, serverName); + } + + /// + public void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid) + { + AddCOMObject(itemName, flags, clsid, null); + } + + /// + public void AddCOMObject(string itemName, HostItemFlags flags, Guid clsid, string serverName) + { + AddHostItem(itemName, flags, MiscHelpers.CreateCOMObject(clsid, serverName)); + } + + /// + public void AddHostType(Type type) + { + AddHostType(HostItemFlags.None, type); + } + + /// + public void AddHostType(HostItemFlags flags, Type type) + { + AddHostType(type.GetRootName(), flags, type); + } + + /// + public void AddHostType(string itemName, Type type) + { + AddHostType(itemName, HostItemFlags.None, type); + } + + /// + public void AddHostType(string itemName, HostItemFlags flags, Type type) + { + MiscHelpers.VerifyNonNullArgument(type, nameof(type)); + AddHostItem(itemName, flags, HostType.Wrap(type)); + } + + /// + public void AddHostType(string itemName, string typeName, params Type[] typeArgs) + { + AddHostType(itemName, HostItemFlags.None, typeName, typeArgs); + } + + /// + public void AddHostType(string itemName, HostItemFlags flags, string typeName, params Type[] typeArgs) + { + AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, null, false, typeArgs)); + } + + /// + public void AddHostType(string itemName, string typeName, string assemblyName, params Type[] typeArgs) + { + AddHostType(itemName, HostItemFlags.None, typeName, assemblyName, typeArgs); + } + + /// + public void AddHostType(string itemName, HostItemFlags flags, string typeName, string assemblyName, params Type[] typeArgs) + { + AddHostItem(itemName, flags, TypeHelpers.ImportType(typeName, assemblyName, true, typeArgs)); + } + + /// + public void AddHostTypes(params Type[] types) + { + if (types != null) + { + foreach (var type in types) + { + if (type != null) + { + AddHostType(type); + } + } + } + } + + /// + public void AddCOMType(string itemName, string progID) + { + AddCOMType(itemName, HostItemFlags.None, progID); + } + + /// + public void AddCOMType(string itemName, string progID, string serverName) + { + AddCOMType(itemName, HostItemFlags.None, progID, serverName); + } + + /// + public void AddCOMType(string itemName, HostItemFlags flags, string progID) + { + AddCOMType(itemName, flags, progID, null); + } + + /// + public void AddCOMType(string itemName, HostItemFlags flags, string progID, string serverName) + { + AddHostItem(itemName, flags, HostType.Wrap(MiscHelpers.GetCOMType(progID, serverName))); + } + + /// + public void AddCOMType(string itemName, Guid clsid) + { + AddCOMType(itemName, HostItemFlags.None, clsid); + } + + /// + public void AddCOMType(string itemName, Guid clsid, string serverName) + { + AddCOMType(itemName, HostItemFlags.None, clsid, serverName); + } + + /// + public void AddCOMType(string itemName, HostItemFlags flags, Guid clsid) + { + AddCOMType(itemName, flags, clsid, null); + } + + /// + public void AddCOMType(string itemName, HostItemFlags flags, Guid clsid, string serverName) + { + AddHostItem(itemName, flags, HostType.Wrap(MiscHelpers.GetCOMType(clsid, serverName))); + } + + /// + public void Execute(string code) + { + Execute(null, code); + } + + /// + public void Execute(string documentName, string code) + { + Execute(documentName, false, code); + } + + /// + public void Execute(string documentName, bool discard, string code) + { + Execute(new DocumentInfo(documentName) { Flags = discard ? DocumentFlags.IsTransient : DocumentFlags.None }, code); + } + + /// + public void Execute(DocumentInfo documentInfo, string code) + { + Execute(documentInfo.MakeUnique(this), code, false); + } + + /// + public void ExecuteDocument(string specifier) + { + ExecuteDocument(specifier, null); + } + + /// + public void ExecuteDocument(string specifier, DocumentCategory category) + { + ExecuteDocument(specifier, category, null); + } + + /// + public void ExecuteDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + Execute(document.Info, document.GetTextContents()); + } + + /// + public virtual string ExecuteCommand(string command) + { + var documentInfo = new DocumentInfo("Command") { Flags = DocumentFlags.IsTransient }; + return GetCommandResultString(Evaluate(documentInfo.MakeUnique(this), command, false)); + } + + /// + public object Evaluate(string code) + { + return Evaluate(null, code); + } + + /// + public object Evaluate(string documentName, string code) + { + return Evaluate(documentName, true, code); + } + + /// + public object Evaluate(string documentName, bool discard, string code) + { + return Evaluate(new DocumentInfo(documentName) { Flags = discard ? DocumentFlags.IsTransient : DocumentFlags.None }, code); + } + + /// + public object Evaluate(DocumentInfo documentInfo, string code) + { + return Evaluate(documentInfo.MakeUnique(this, DocumentFlags.IsTransient), code, true); + } + + /// + public object EvaluateDocument(string specifier) + { + return EvaluateDocument(specifier, null); + } + + /// + public object EvaluateDocument(string specifier, DocumentCategory category) + { + return EvaluateDocument(specifier, category, null); + } + + /// + public object EvaluateDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Evaluate(document.Info, document.GetTextContents()); + } + + /// + public object Invoke(string funcName, params object[] args) + { + MiscHelpers.VerifyNonBlankArgument(funcName, nameof(funcName), "Invalid function name"); + return Global.InvokeMethod(funcName, args ?? ArrayHelpers.GetEmptyArray()); + } + + /// + public abstract string GetStackTrace(); + + /// + public abstract void Interrupt(); + + /// + public abstract void CollectGarbage(bool exhaustive); + + #endregion + + #region internal members + + internal abstract IUniqueNameManager DocumentNameManager { get; } + + internal virtual bool EnumerateInstanceMethods => true; + + internal virtual bool EnumerateExtensionMethods => EnumerateInstanceMethods; + + internal virtual bool UseCaseInsensitiveMemberBinding => false; + + internal abstract void AddHostItem(string itemName, HostItemFlags flags, object item); + + internal object PrepareResult(T result, ScriptMemberFlags flags, bool isListIndexResult) + { + return PrepareResult(result, typeof(T), flags, isListIndexResult); + } + + internal virtual object PrepareResult(object result, Type type, ScriptMemberFlags flags, bool isListIndexResult) + { + var wrapNull = flags.HasFlag(ScriptMemberFlags.WrapNullResult) || EnableNullResultWrapping; + if (wrapNull && (result == null)) + { + return HostObject.WrapResult(null, type, true); + } + + if (!flags.HasFlag(ScriptMemberFlags.ExposeRuntimeType) && !DisableTypeRestriction && (!isListIndexResult || !DisableListIndexTypeRestriction)) + { + return HostObject.WrapResult(result, type, wrapNull); + } + + return result; + } + + internal abstract object MarshalToScript(object obj, HostItemFlags flags); + + internal object MarshalToScript(object obj) + { + var hostItem = obj as HostItem; + return MarshalToScript(obj, hostItem?.Flags ?? HostItemFlags.None); + } + + internal object[] MarshalToScript(object[] args) + { + return args.Select(MarshalToScript).ToArray(); + } + + internal abstract object MarshalToHost(object obj, bool preserveHostTarget); + + internal object[] MarshalToHost(object[] args, bool preserveHostTargets) + { + return args.Select(arg => MarshalToHost(arg, preserveHostTargets)).ToArray(); + } + + internal abstract object Execute(UniqueDocumentInfo documentInfo, string code, bool evaluate); + + internal abstract object ExecuteRaw(UniqueDocumentInfo documentInfo, string code, bool evaluate); + + internal object Evaluate(UniqueDocumentInfo documentInfo, string code, bool marshalResult) + { + var result = Execute(documentInfo, code, true); + if (marshalResult) + { + result = MarshalToHost(result, false); + } + + return result; + } + + internal string GetCommandResultString(object result) + { + if (result is HostItem hostItem) + { + if (hostItem.Target is IHostVariable) + { + return result.ToString(); + } + } + + var marshaledResult = MarshalToHost(result, false); + + if (marshaledResult is VoidResult) + { + return null; + } + + if (marshaledResult == null) + { + return "[null]"; + } + + if (marshaledResult is Undefined) + { + return marshaledResult.ToString(); + } + + if (marshaledResult is ScriptItem) + { + return "[ScriptObject]"; + } + + return result.ToString(); + } + + internal void RequestInterrupt() + { + // Some script engines don't support IActiveScript::InterruptScriptThread(). This + // method provides an alternate mechanism based on IActiveScriptSiteInterruptPoll. + + var tempScriptFrame = CurrentScriptFrame; + if (tempScriptFrame != null) + { + tempScriptFrame.InterruptRequested = true; + } + } + + internal void CheckReflection() + { + if (!AllowReflection) + { + throw new UnauthorizedAccessException("Use of reflection is prohibited in this script engine"); + } + } + + internal virtual void OnAccessSettingsChanged() + { + ClearConstructorBindCache(); + ClearPropertyBindCache(); + } + + #endregion + + #region host-side invocation + + internal virtual void HostInvoke(Action action) + { + action(); + } + + internal virtual T HostInvoke(Func func) + { + return func(); + } + + #endregion + + #region script-side invocation + + internal ScriptFrame CurrentScriptFrame { get; private set; } + + internal IDisposable CreateEngineScope() + { + return Scope.Create(() => MiscHelpers.Exchange(ref currentEngine, this), previousEngine => currentEngine = previousEngine); + } + + internal virtual void ScriptInvoke(Action action) + { + using (CreateEngineScope()) + { + ScriptInvokeInternal(action); + } + } + + internal virtual T ScriptInvoke(Func func) + { + using (CreateEngineScope()) + { + return ScriptInvokeInternal(func); + } + } + + internal void ScriptInvokeInternal(Action action) + { + var previousScriptFrame = CurrentScriptFrame; + CurrentScriptFrame = new ScriptFrame(); + + try + { + action(); + } + finally + { + CurrentScriptFrame = previousScriptFrame; + } + } + + internal T ScriptInvokeInternal(Func func) + { + var previousScriptFrame = CurrentScriptFrame; + CurrentScriptFrame = new ScriptFrame(); + + try + { + return func(); + } + finally + { + CurrentScriptFrame = previousScriptFrame; + } + } + + internal void ThrowScriptError() + { + if (CurrentScriptFrame != null) + { + ThrowScriptError(CurrentScriptFrame.ScriptError); + } + } + + internal static void ThrowScriptError(IScriptEngineException scriptError) + { + if (scriptError != null) + { + if (scriptError is ScriptInterruptedException) + { + throw new ScriptInterruptedException(scriptError.EngineName, scriptError.Message, scriptError.ErrorDetails, scriptError.HResult, scriptError.IsFatal, scriptError.ExecutionStarted, scriptError.ScriptExceptionAsObject, scriptError.InnerException); + } + + throw new ScriptEngineException(scriptError.EngineName, scriptError.Message, scriptError.ErrorDetails, scriptError.HResult, scriptError.IsFatal, scriptError.ExecutionStarted, scriptError.ScriptExceptionAsObject, scriptError.InnerException); + } + } + + #endregion + + #region synchronized invocation + + internal virtual void SyncInvoke(Action action) + { + action(); + } + + internal virtual T SyncInvoke(Func func) + { + return func(); + } + + #endregion + + #region enumeration settings + + internal object EnumerationSettingsToken { get; private set; } = new object(); + + internal void OnEnumerationSettingsChanged() + { + EnumerationSettingsToken = new object(); + } + + #endregion + + #region extension method table + + private static readonly ExtensionMethodTable emptyExtensionMethodTable = new ExtensionMethodTable(); + + private readonly ExtensionMethodTable realExtensionMethodTable; + private ExtensionMethodTable extensionMethodTable; + + internal void ProcessExtensionMethodType(Type type) + { + if (extensionMethodTable != emptyExtensionMethodTable) + { + if (extensionMethodTable.ProcessType(this, type)) + { + ClearMethodBindCache(); + } + } + } + + internal ExtensionMethodSummary ExtensionMethodSummary => extensionMethodTable.Summary; + + internal void RebuildExtensionMethodSummary() + { + if (extensionMethodTable != emptyExtensionMethodTable) + { + extensionMethodTable.RebuildSummary(this); + } + } + + #endregion + + #region constructor bind cache + + private readonly Dictionary constructorBindCache = new Dictionary(); + + internal void CacheConstructorBindResult(BindSignature signature, ConstructorInfo result) + { + constructorBindCache[signature] = result; + } + + internal bool TryGetCachedConstructorBindResult(BindSignature signature, out ConstructorInfo result) + { + return constructorBindCache.TryGetValue(signature, out result); + } + + private void ClearConstructorBindCache() + { + constructorBindCache.Clear(); + } + + #endregion + + #region method bind cache + + private readonly Dictionary methodBindCache = new Dictionary(); + + internal void CacheMethodBindResult(BindSignature signature, object result) + { + methodBindCache[signature] = result; + } + + internal bool TryGetCachedMethodBindResult(BindSignature signature, out object result) + { + return methodBindCache.TryGetValue(signature, out result); + } + + private void ClearMethodBindCache() + { + methodBindCache.Clear(); + } + + #endregion + + #region property bind cache + + private readonly Dictionary propertyGetBindCache = new Dictionary(); + private readonly Dictionary propertySetBindCache = new Dictionary(); + + internal void CachePropertyGetBindResult(BindSignature signature, MemberInfo property) + { + propertyGetBindCache[signature] = property; + } + + internal bool TryGetCachedPropertyGetBindResult(BindSignature signature, out MemberInfo property) + { + return propertyGetBindCache.TryGetValue(signature, out property); + } + + internal void CachePropertySetBindResult(BindSignature signature, MemberInfo property) + { + propertySetBindCache[signature] = property; + } + + internal bool TryGetCachedPropertySetBindResult(BindSignature signature, out MemberInfo property) + { + return propertySetBindCache.TryGetValue(signature, out property); + } + + private void ClearPropertyBindCache() + { + propertyGetBindCache.Clear(); + propertySetBindCache.Clear(); + } + + #endregion + + #region host item cache + + private readonly ConditionalWeakTable> hostObjectHostItemCache = new ConditionalWeakTable>(); + private readonly ConditionalWeakTable> hostTypeHostItemCache = new ConditionalWeakTable>(); + + internal HostItem GetOrCreateHostItem(HostTarget target, HostItemFlags flags, HostItem.CreateFunc createHostItem) + { + if (target is HostObject hostObject) + { + return GetOrCreateHostItemForHostObject(hostObject, hostObject.Target, flags, createHostItem); + } + + if (target is HostType hostType) + { + return GetOrCreateHostItemForHostType(hostType, flags, createHostItem); + } + + if (target is HostMethod hostMethod) + { + return GetOrCreateHostItemForHostObject(hostMethod, hostMethod, flags, createHostItem); + } + + if (target is HostVariable hostVariable) + { + return GetOrCreateHostItemForHostObject(hostVariable, hostVariable, flags, createHostItem); + } + + if (target is HostIndexedProperty hostIndexedProperty) + { + return GetOrCreateHostItemForHostObject(hostIndexedProperty, hostIndexedProperty, flags, createHostItem); + } + + return CreateHostItem(target, flags, createHostItem, null); + } + + private HostItem GetOrCreateHostItemForHostObject(HostTarget hostTarget, object target, HostItemFlags flags, HostItem.CreateFunc createHostItem) + { + var cacheEntry = hostObjectHostItemCache.GetOrCreateValue(target ?? nullHostObjectProxy); + + List activeWeakRefs = null; + var staleWeakRefCount = 0; + + foreach (var weakRef in cacheEntry) + { + var hostItem = weakRef.Target as HostItem; + if (hostItem == null) + { + staleWeakRefCount++; + } + else + { + if ((hostItem.Target.Type == hostTarget.Type) && (hostItem.Flags == flags)) + { + return hostItem; + } + + if (activeWeakRefs == null) + { + activeWeakRefs = new List(cacheEntry.Count); + } + + activeWeakRefs.Add(weakRef); + } + } + + if (staleWeakRefCount > 4) + { + cacheEntry.Clear(); + if (activeWeakRefs != null) + { + cacheEntry.Capacity = activeWeakRefs.Count + 1; + cacheEntry.AddRange(activeWeakRefs); + } + } + + return CreateHostItem(hostTarget, flags, createHostItem, cacheEntry); + } + + private HostItem GetOrCreateHostItemForHostType(HostType hostType, HostItemFlags flags, HostItem.CreateFunc createHostItem) + { + if (hostType.Types.Length != 1) + { + return CreateHostItem(hostType, flags, createHostItem, null); + } + + var cacheEntry = hostTypeHostItemCache.GetOrCreateValue(hostType.Types[0]); + + List activeWeakRefs = null; + var staleWeakRefCount = 0; + + foreach (var weakRef in cacheEntry) + { + var hostItem = weakRef.Target as HostItem; + if (hostItem == null) + { + staleWeakRefCount++; + } + else + { + if (hostItem.Flags == flags) + { + return hostItem; + } + + if (activeWeakRefs == null) + { + activeWeakRefs = new List(cacheEntry.Count); + } + + activeWeakRefs.Add(weakRef); + } + } + + if (staleWeakRefCount > 4) + { + cacheEntry.Clear(); + if (activeWeakRefs != null) + { + cacheEntry.Capacity = activeWeakRefs.Count + 1; + cacheEntry.AddRange(activeWeakRefs); + } + } + + return CreateHostItem(hostType, flags, createHostItem, cacheEntry); + } + + private HostItem CreateHostItem(HostTarget hostTarget, HostItemFlags flags, HostItem.CreateFunc createHostItem, List cacheEntry) + { + var newHostItem = createHostItem(this, hostTarget, flags); + + if (cacheEntry != null) + { + cacheEntry.Add(new WeakReference(newHostItem)); + } + + if (hostTarget.Target is IScriptableObject scriptableObject) + { + scriptableObject.OnExposedToScriptCode(this); + } + + return newHostItem; + } + + #endregion + + #region host item collateral + + internal abstract HostItemCollateral HostItemCollateral { get; } + + #endregion + + #region shared host target member data + + internal readonly HostTargetMemberData SharedHostMethodMemberData = new HostTargetMemberData(); + internal readonly HostTargetMemberData SharedHostIndexedPropertyMemberData = new HostTargetMemberData(); + internal readonly HostTargetMemberData SharedScriptMethodMemberData = new HostTargetMemberData(); + + private readonly ConditionalWeakTable> sharedHostObjectMemberDataCache = new ConditionalWeakTable>(); + + internal HostTargetMemberData GetSharedHostObjectMemberData(HostObject target, CustomAttributeLoader targetCustomAttributeLoader, Type targetAccessContext, ScriptAccess targetDefaultAccess, HostTargetFlags targetFlags) + { + var cacheEntry = sharedHostObjectMemberDataCache.GetOrCreateValue(target.Type); + + List activeWeakRefs = null; + var staleWeakRefCount = 0; + + foreach (var weakRef in cacheEntry) + { + var memberData = weakRef.Target as HostTargetMemberDataWithContext; + if (memberData == null) + { + staleWeakRefCount++; + } + else + { + if ((memberData.CustomAttributeLoader == targetCustomAttributeLoader) && (memberData.AccessContext == targetAccessContext) && (memberData.DefaultAccess == targetDefaultAccess) && (memberData.TargetFlags == targetFlags)) + { + return memberData; + } + + if (activeWeakRefs == null) + { + activeWeakRefs = new List(cacheEntry.Count); + } + + activeWeakRefs.Add(weakRef); + } + } + + if (staleWeakRefCount > 4) + { + cacheEntry.Clear(); + if (activeWeakRefs != null) + { + cacheEntry.Capacity = activeWeakRefs.Count + 1; + cacheEntry.AddRange(activeWeakRefs); + } + } + + var newMemberData = new HostTargetMemberDataWithContext(targetCustomAttributeLoader, targetAccessContext, targetDefaultAccess, targetFlags); + cacheEntry.Add(new WeakReference(newMemberData)); + return newMemberData; + } + + #endregion + + #region event connections + + private readonly EventConnectionMap eventConnectionMap = new EventConnectionMap(); + + internal EventConnection CreateEventConnection(Type handlerType, object source, EventInfo eventInfo, Delegate handler) + { + return eventConnectionMap.Create(this, handlerType, source, eventInfo, handler); + } + + internal EventConnection CreateEventConnection(object source, EventInfo eventInfo, Delegate handler) + { + return eventConnectionMap.Create(this, source, eventInfo, handler); + } + + internal void BreakEventConnection(EventConnection connection) + { + eventConnectionMap.Break(connection); + } + + private void BreakAllEventConnections() + { + eventConnectionMap.Dispose(); + } + + #endregion + + #region disposal / finalization + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the script engine and optionally releases the managed resources. + /// + /// True to release both managed and unmanaged resources; false to release only unmanaged resources. + /// + /// This method is called by the public method and the + /// Finalize method. invokes the + /// protected Dispose(Boolean) method with the + /// parameter set to true. Finalize invokes + /// Dispose(Boolean) with set to false. + /// + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + BreakAllEventConnections(); + } + } + + /// + /// Releases unmanaged resources and performs other cleanup operations before the script engine is reclaimed by garbage collection. + /// + /// + /// This method overrides . Application code should not + /// call this method; an object's Finalize() method is automatically invoked during + /// garbage collection, unless finalization by the garbage collector has been disabled by a + /// call to . + /// + ~ScriptEngine() + { + Dispose(false); + } + + #endregion + + #region IHostContext implementation + + ScriptEngine IHostContext.Engine => this; + + #endregion + + #region Nested type: ScriptFrame + + internal sealed class ScriptFrame + { + public Exception HostException { get; set; } + + public IScriptEngineException ScriptError { get; set; } + + public IScriptEngineException PendingScriptError { get; set; } + + public bool InterruptRequested { get; set; } + } + + #endregion + + #region Nested type: EventConnectionMap + + private sealed class EventConnectionMap : IDisposable + { + private readonly HashSet map = new HashSet(); + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + internal EventConnection Create(ScriptEngine engine, Type handlerType, object source, EventInfo eventInfo, Delegate handler) + { + var connection = (EventConnection)typeof(EventConnection<>).MakeGenericType(handlerType).CreateInstance(BindingFlags.NonPublic, engine, source, eventInfo, handler); + Add(connection); + return connection; + } + + internal EventConnection Create(ScriptEngine engine, object source, EventInfo eventInfo, Delegate handler) + { + var connection = new EventConnection(engine, source, eventInfo, handler); + Add(connection); + return connection; + } + + private void Add(EventConnection connection) + { + if (!disposedFlag.IsSet) + { + lock (map) + { + map.Add(connection); + } + } + } + + internal void Break(EventConnection connection) + { + var mustBreak = true; + + if (!disposedFlag.IsSet) + { + lock (map) + { + mustBreak = map.Remove(connection); + } + } + + if (mustBreak) + { + connection.Break(); + } + } + + public void Dispose() + { + if (disposedFlag.Set()) + { + var connections = new List(); + + lock (map) + { + connections.AddRange(map); + } + + connections.ForEach(connection => connection.Break()); + } + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptEngine.cs.meta b/Unity/Package/Runtime/ScriptEngine.cs.meta new file mode 100644 index 000000000..7e926b2f4 --- /dev/null +++ b/Unity/Package/Runtime/ScriptEngine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 915d3e0a79c6d384997b003761931e8c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptEngineException.cs b/Unity/Package/Runtime/ScriptEngineException.cs new file mode 100644 index 000000000..81d1a1da4 --- /dev/null +++ b/Unity/Package/Runtime/ScriptEngineException.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.Serialization; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// The exception that is thrown when an error occurs during script execution or script object access. + /// + [Serializable] + public class ScriptEngineException : InvalidOperationException, IScriptEngineException + { + private readonly string engineName; + private const string engineNameItemName = "ScriptEngineName"; + + private readonly string errorDetails; + private const string errorDetailsItemName = "ScriptErrorDetails"; + + private readonly bool isFatal; + private const string isFatalItemName = "IsFatal"; + + private readonly bool executionStarted; + private const string executionStartedItemName = "ExecutionStarted"; + + private readonly object scriptException; + private const string defaultMessage = "An error occurred during script execution"; + + #region constructors + + /// + /// Initializes a new instance. + /// + public ScriptEngineException() + : base(defaultMessage) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with the specified error message. + /// + /// The error message. + public ScriptEngineException(string message) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage)) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with the specified error message and nested exception. + /// + /// The error message. + /// The exception that caused the current exception to be thrown. + public ScriptEngineException(string message, Exception innerException) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage), innerException) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with serialized data. + /// + /// The object that holds the serialized data. + /// The contextual information about the source or destination. + protected ScriptEngineException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + engineName = info.GetString(engineNameItemName); + errorDetails = info.GetString(errorDetailsItemName); + isFatal = info.GetBoolean(isFatalItemName); + executionStarted = info.GetBoolean(executionStartedItemName); + } + + internal ScriptEngineException(string engineName, string message, string errorDetails, int errorCode, bool isFatal, bool executionStarted, object scriptException, Exception innerException) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage), innerException) + { + this.engineName = engineName; + this.errorDetails = MiscHelpers.EnsureNonBlank(errorDetails, base.Message); + this.isFatal = isFatal; + this.executionStarted = executionStarted; + this.scriptException = scriptException; + + if (errorCode != 0) + { + HResult = errorCode; + } + } + + #endregion + + #region IScriptEngineException implementation + + /// + /// Gets an HRESULT error code if one is available, zero otherwise. + /// + int IScriptEngineException.HResult => HResult; + + /// + /// Gets the name associated with the script engine instance. + /// + public string EngineName => engineName; + + /// + /// Gets a detailed error message if one is available, null otherwise. + /// + public string ErrorDetails => errorDetails; + + /// + /// Gets a value that indicates whether the exception represents a fatal error. + /// + public bool IsFatal => isFatal; + + /// + /// Gets a value that indicates whether script code execution had started before the current exception was thrown. + /// + public bool ExecutionStarted => executionStarted; + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified. + /// + public dynamic ScriptException => scriptException; + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified, without engaging the dynamic infrastructure. + /// + public object ScriptExceptionAsObject => scriptException; + + #endregion + + #region Object overrides + + /// + /// Returns a string that represents the current exception. + /// + /// A string that represents the current exception. + public override string ToString() + { + var result = base.ToString(); + + if (!string.IsNullOrEmpty(errorDetails) && (errorDetails != Message)) + { + var details = " " + errorDetails.Replace("\n", "\n "); + result += "\n --- Script error details follow ---\n" + details; + } + + return result; + } + + #endregion + + #region InvalidOperationException overrides + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue(engineNameItemName, engineName); + info.AddValue(errorDetailsItemName, errorDetails); + info.AddValue(isFatalItemName, isFatal); + info.AddValue(executionStartedItemName, executionStarted); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptEngineException.cs.meta b/Unity/Package/Runtime/ScriptEngineException.cs.meta new file mode 100644 index 000000000..77df6bb11 --- /dev/null +++ b/Unity/Package/Runtime/ScriptEngineException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8dca6cd131770a34fa9a58e5b73ed383 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptInterruptedException.cs b/Unity/Package/Runtime/ScriptInterruptedException.cs new file mode 100644 index 000000000..554c37f08 --- /dev/null +++ b/Unity/Package/Runtime/ScriptInterruptedException.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.Serialization; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + /// + /// The exception that is thrown when script execution is interrupted by the host. + /// + [Serializable] + public class ScriptInterruptedException : OperationCanceledException, IScriptEngineException + { + private readonly string engineName; + private const string engineNameItemName = "ScriptEngineName"; + + private readonly string errorDetails; + private const string errorDetailsItemName = "ScriptErrorDetails"; + + private readonly bool isFatal; + private const string isFatalItemName = "IsFatal"; + + private readonly bool executionStarted; + private const string executionStartedItemName = "ExecutionStarted"; + + private readonly object scriptException; + private const string defaultMessage = "Script execution was interrupted"; + + #region constructors + + /// + /// Initializes a new instance. + /// + public ScriptInterruptedException() + : base(defaultMessage) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with the specified error message. + /// + /// The error message. + public ScriptInterruptedException(string message) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage)) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with the specified error message and nested exception. + /// + /// The error message. + /// The exception that caused the current exception to be thrown. + public ScriptInterruptedException(string message, Exception innerException) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage), innerException) + { + errorDetails = base.Message; + } + + /// + /// Initializes a new with serialized data. + /// + /// The object that holds the serialized data. + /// The contextual information about the source or destination. + protected ScriptInterruptedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + engineName = info.GetString(engineNameItemName); + errorDetails = info.GetString(errorDetailsItemName); + isFatal = info.GetBoolean(isFatalItemName); + executionStarted = info.GetBoolean(executionStartedItemName); + } + + internal ScriptInterruptedException(string engineName, string message, string errorDetails, int errorCode, bool isFatal, bool executionStarted, object scriptException, Exception innerException) + : base(MiscHelpers.EnsureNonBlank(message, defaultMessage), innerException) + { + this.engineName = engineName; + this.errorDetails = MiscHelpers.EnsureNonBlank(errorDetails, base.Message); + this.isFatal = isFatal; + this.executionStarted = executionStarted; + this.scriptException = scriptException; + + if (errorCode != 0) + { + HResult = errorCode; + } + } + + #endregion + + #region IScriptEngineException implementation + + /// + /// Gets an HRESULT error code if one is available, zero otherwise. + /// + int IScriptEngineException.HResult => HResult; + + /// + /// Gets the name associated with the script engine instance. + /// + public string EngineName => engineName; + + /// + /// Gets a detailed error message if one is available, null otherwise. + /// + public string ErrorDetails => errorDetails; + + /// + /// Gets a value that indicates whether the exception represents a fatal error. + /// + public bool IsFatal => isFatal; + + /// + /// Gets a value that indicates whether script code execution had started before the current exception was thrown. + /// + public bool ExecutionStarted => executionStarted; + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified. + /// + public dynamic ScriptException => scriptException; + + /// + /// Gets the script exception that caused the current exception to be thrown, or null if one was not specified, without engaging the dynamic infrastructure. + /// + public object ScriptExceptionAsObject => scriptException; + + #endregion + + #region Object overrides + + /// + /// Returns a string that represents the current exception. + /// + /// A string that represents the current exception. + public override string ToString() + { + var result = base.ToString(); + + if (!string.IsNullOrEmpty(errorDetails) && (errorDetails != Message)) + { + var details = " " + errorDetails.Replace("\n", "\n "); + result += "\n --- Script error details follow ---\n" + details; + } + + return result; + } + + #endregion + + #region OperationCanceledException overrides + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue(engineNameItemName, engineName); + info.AddValue(errorDetailsItemName, errorDetails); + info.AddValue(isFatalItemName, isFatal); + info.AddValue(executionStartedItemName, executionStarted); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptInterruptedException.cs.meta b/Unity/Package/Runtime/ScriptInterruptedException.cs.meta new file mode 100644 index 000000000..3590a7e70 --- /dev/null +++ b/Unity/Package/Runtime/ScriptInterruptedException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b97ac8bea675d34380702f394878fc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptItem.cs b/Unity/Package/Runtime/ScriptItem.cs new file mode 100644 index 000000000..a2f9f5fe7 --- /dev/null +++ b/Unity/Package/Runtime/ScriptItem.cs @@ -0,0 +1,454 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.InteropServices.Expando; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal abstract class ScriptItem : ScriptObject, IExpando, IDynamic, IScriptMarshalWrapper + { + private static readonly MethodInfo throwLastScriptErrorMethod = typeof(ScriptItem).GetMethod("ThrowLastScriptError"); + private static readonly MethodInfo clearLastScriptErrorMethod = typeof(ScriptItem).GetMethod("ClearLastScriptError"); + [ThreadStatic] private static IScriptEngineException lastScriptError; + + public static void ThrowLastScriptError() + { + var scriptError = lastScriptError; + if (scriptError != null) + { + if (scriptError is ScriptInterruptedException) + { + throw new ScriptInterruptedException(scriptError.EngineName, scriptError.Message, scriptError.ErrorDetails, scriptError.HResult, scriptError.IsFatal, scriptError.ExecutionStarted, scriptError.ScriptExceptionAsObject, scriptError.InnerException); + } + + throw new ScriptEngineException(scriptError.EngineName, scriptError.Message, scriptError.ErrorDetails, scriptError.HResult, scriptError.IsFatal, scriptError.ExecutionStarted, scriptError.ScriptExceptionAsObject, scriptError.InnerException); + } + } + + public static void ClearLastScriptError() + { + lastScriptError = null; + } + + protected abstract bool TryBindAndInvoke(DynamicMetaObjectBinder binder, object[] args, out object result); + + protected virtual object[] AdjustInvokeArgs(object[] args) + { + return args; + } + + private bool TryWrappedBindAndInvoke(DynamicMetaObjectBinder binder, object[] wrappedArgs, out object result) + { + object[] args = null; + object[] savedArgs = null; + + object tempResult = null; + var succeeded = Engine.ScriptInvoke(() => + { + args = Engine.MarshalToScript(wrappedArgs); + savedArgs = (object[])args.Clone(); + + if (!TryBindAndInvoke(binder, args, out tempResult)) + { + if ((Engine.CurrentScriptFrame != null) && (lastScriptError == null)) + { + lastScriptError = Engine.CurrentScriptFrame.ScriptError; + } + + return false; + } + + return true; + }); + + if (succeeded) + { + for (var index = 0; index < args.Length; index++) + { + var arg = args[index]; + if (!ReferenceEquals(arg, savedArgs[index])) + { + wrappedArgs[index] = Engine.MarshalToHost(args[index], false); + } + } + + result = Engine.MarshalToHost(tempResult, false).ToDynamicResult(Engine); + return true; + } + + result = null; + return false; + } + + private bool TryWrappedInvokeOrInvokeMember(DynamicMetaObjectBinder binder, ParameterInfo[] parameters, object[] args, out object result) + { + Type[] paramTypes = null; + if ((parameters != null) && (parameters.Length >= args.Length)) + { + paramTypes = parameters.Skip(parameters.Length - args.Length).Select(param => param.ParameterType).ToArray(); + } + + if (paramTypes != null) + { + for (var index = 0; index < paramTypes.Length; index++) + { + var paramType = paramTypes[index]; + if (paramType.IsByRef) + { + args[index] = typeof(HostVariable<>).MakeSpecificType(paramType.GetElementType()).CreateInstance(args[index]); + } + } + } + + if (TryWrappedBindAndInvoke(binder, AdjustInvokeArgs(args), out result)) + { + if (paramTypes != null) + { + for (var index = 0; index < paramTypes.Length; index++) + { + if (paramTypes[index].IsByRef) + { + if (args[index] is IHostVariable hostVariable) + { + args[index] = hostVariable.Value; + } + } + } + } + + return true; + } + + return false; + } + + private string[] GetAllPropertyNames() + { + return GetPropertyNames().Concat(GetPropertyIndices().Select(index => index.ToString(CultureInfo.InvariantCulture))).ToArray(); + } + + private static DynamicMetaObject PostProcessBindResult(DynamicMetaObject result) + { + var catchBody = Expression.Block(Expression.Call(throwLastScriptErrorMethod), Expression.Rethrow(), Expression.Default(result.Expression.Type)); + return new DynamicMetaObject(Expression.TryCatchFinally(result.Expression, Expression.Call(clearLastScriptErrorMethod), Expression.Catch(typeof(Exception), catchBody)), result.Restrictions); + } + + #region ScriptObject overrides + + public override IEnumerable PropertyNames => GetPropertyNames(); + + public override IEnumerable PropertyIndices => GetPropertyIndices(); + + public override object this[string name, params object[] args] + { + get => GetProperty(name, args).ToDynamicResult(Engine); + set => SetProperty(name, args.Concat(value.ToEnumerable()).ToArray()); + } + + public override object this[int index] + { + get => GetProperty(index).ToDynamicResult(Engine); + set => SetProperty(index, value); + } + + #endregion + + #region DynamicObject overrides + + public override DynamicMetaObject GetMetaObject(Expression param) + { + return new MetaScriptItem(base.GetMetaObject(param)); + } + + public override IEnumerable GetDynamicMemberNames() + { + return GetPropertyNames().Concat(GetPropertyIndices().Select(index => index.ToString(CultureInfo.InvariantCulture))); + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + return TryWrappedBindAndInvoke(binder, ArrayHelpers.GetEmptyArray(), out result); + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + return TryWrappedBindAndInvoke(binder, new[] { value }, out _); + } + + public override bool TryGetIndex(GetIndexBinder binder, object[] indices, out object result) + { + return TryWrappedBindAndInvoke(binder, indices, out result); + } + + public override bool TrySetIndex(SetIndexBinder binder, object[] indices, object value) + { + return TryWrappedBindAndInvoke(binder, indices.Concat(value.ToEnumerable()).ToArray(), out _); + } + + public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) + { + ParameterInfo[] parameters = null; + if (Engine.EnableAutoHostVariables) + { + parameters = new StackFrame(1, false).GetMethod().GetParameters(); + } + + return TryWrappedInvokeOrInvokeMember(binder, parameters, args, out result); + } + + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + ParameterInfo[] parameters = null; + if (Engine.EnableAutoHostVariables) + { + parameters = new StackFrame(1, false).GetMethod().GetParameters(); + } + + return TryWrappedInvokeOrInvokeMember(binder, parameters, args, out result); + } + + #endregion + + #region IReflect implementation + + public MethodInfo GetMethod(string name, BindingFlags bindFlags, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public MethodInfo GetMethod(string name, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + public MethodInfo[] GetMethods(BindingFlags bindFlags) + { + return ArrayHelpers.GetEmptyArray(); + } + + public FieldInfo GetField(string name, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + public FieldInfo[] GetFields(BindingFlags bindFlags) + { + return MemberMap.GetFields(GetAllPropertyNames()); + } + + public PropertyInfo GetProperty(string name, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + public PropertyInfo GetProperty(string name, BindingFlags bindFlags, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public PropertyInfo[] GetProperties(BindingFlags bindFlags) + { + return ArrayHelpers.GetEmptyArray(); + } + + public MemberInfo[] GetMember(string name, BindingFlags bindFlags) + { + // ReSharper disable once CoVariantArrayConversion + return new [] { MemberMap.GetField(name) }; + } + + public MemberInfo[] GetMembers(BindingFlags bindFlags) + { + // ReSharper disable once CoVariantArrayConversion + return GetFields(bindFlags); + } + + public object InvokeMember(string name, BindingFlags invokeFlags, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) + { + if (invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + { + if (name == SpecialMemberNames.Default) + { + return Invoke(false, args); + } + + return InvokeMethod(name, args); + } + + if (invokeFlags.HasFlag(BindingFlags.GetField)) + { + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + return GetProperty(index); + } + + return GetProperty(name, args); + } + + if (invokeFlags.HasFlag(BindingFlags.SetField)) + { + if (args.Length != 1) + { + throw new InvalidOperationException("Invalid argument count"); + } + + var value = args[0]; + + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + SetProperty(index, value); + return value; + } + + SetProperty(name, args); + return value; + } + + throw new InvalidOperationException("Invalid member access mode"); + } + + public Type UnderlyingSystemType => throw new NotImplementedException(); + + #endregion + + #region IExpando implementation + + public FieldInfo AddField(string name) + { + throw new NotImplementedException(); + } + + public PropertyInfo AddProperty(string name) + { + throw new NotImplementedException(); + } + + public MethodInfo AddMethod(string name, Delegate method) + { + throw new NotImplementedException(); + } + + public void RemoveMember(MemberInfo member) + { + throw new NotImplementedException(); + } + + #endregion + + #region IDynamic implementation + + public object GetProperty(string name, out bool isCacheable, params object[] args) + { + isCacheable = false; + return GetProperty(name, args); + } + + #endregion + + #region IDynamic implementation + + public abstract string[] GetPropertyNames(); + public abstract int[] GetPropertyIndices(); + + #endregion + + #region IScriptMarshalWrapper implementation + + public abstract object Unwrap(); + + #endregion + + #region Nested type: MetaScriptItem + + private sealed class MetaScriptItem : DynamicMetaObject + { + private readonly DynamicMetaObject metaDynamic; + + public MetaScriptItem(DynamicMetaObject metaDynamic) + : base(metaDynamic.Expression, metaDynamic.Restrictions, metaDynamic.Value) + { + this.metaDynamic = metaDynamic; + } + + #region DynamicMetaObject overrides + + public override IEnumerable GetDynamicMemberNames() + { + return metaDynamic.GetDynamicMemberNames(); + } + + public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) + { + return PostProcessBindResult(metaDynamic.BindBinaryOperation(binder, arg)); + } + + public override DynamicMetaObject BindConvert(ConvertBinder binder) + { + return PostProcessBindResult(metaDynamic.BindConvert(binder)); + } + + public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) + { + return PostProcessBindResult(metaDynamic.BindCreateInstance(binder, args)); + } + + public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) + { + return PostProcessBindResult(metaDynamic.BindDeleteIndex(binder, indexes)); + } + + public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) + { + return PostProcessBindResult(metaDynamic.BindDeleteMember(binder)); + } + + public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) + { + return PostProcessBindResult(metaDynamic.BindGetIndex(binder, indexes)); + } + + public override DynamicMetaObject BindGetMember(GetMemberBinder binder) + { + return PostProcessBindResult(metaDynamic.BindGetMember(binder)); + } + + public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) + { + return PostProcessBindResult(metaDynamic.BindInvoke(binder, args)); + } + + public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) + { + return PostProcessBindResult(metaDynamic.BindInvokeMember(binder, args)); + } + + public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) + { + return PostProcessBindResult(metaDynamic.BindSetIndex(binder, indexes, value)); + } + + public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) + { + return PostProcessBindResult(metaDynamic.BindSetMember(binder, value)); + } + + public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) + { + return PostProcessBindResult(metaDynamic.BindUnaryOperation(binder)); + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptItem.cs.meta b/Unity/Package/Runtime/ScriptItem.cs.meta new file mode 100644 index 000000000..efb0e0761 --- /dev/null +++ b/Unity/Package/Runtime/ScriptItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 313f017bfdacb744aaae386081fcf86c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptMemberAttribute.cs b/Unity/Package/Runtime/ScriptMemberAttribute.cs new file mode 100644 index 000000000..5d859fc71 --- /dev/null +++ b/Unity/Package/Runtime/ScriptMemberAttribute.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies how the target type member is to be exposed to script code. This extended version + /// supports additional options. + /// + /// + /// This attribute is applicable to events, fields, methods, and properties. + /// + [AttributeUsage(AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property)] + public sealed class ScriptMemberAttribute : ScriptUsageAttribute + { + /// + /// Initializes a new instance. + /// + public ScriptMemberAttribute() + { + } + + /// + /// Initializes a new instance with the specified name. + /// + /// The name that script code will use to access the target type member. + public ScriptMemberAttribute(string name) + { + Name = name; + } + + /// + /// Initializes a new instance with the specified script access setting. + /// + /// The script access setting for the target type member. + public ScriptMemberAttribute(ScriptAccess access) + : base(access) + { + } + + /// + /// Initializes a new instance with the specified name and script access setting. + /// + /// The name that script code will use to access the target type member. + /// The script access setting for the target type member. + public ScriptMemberAttribute(string name, ScriptAccess access) + : base(access) + { + Name = name; + } + + /// + /// Initializes a new instance with the specified script options. + /// + /// The script options for the target type member. + public ScriptMemberAttribute(ScriptMemberFlags flags) + { + Flags = flags; + } + + /// + /// Initializes a new instance with the specified name and script options. + /// + /// The name that script code will use to access the target type member. + /// The script options for the target type member. + public ScriptMemberAttribute(string name, ScriptMemberFlags flags) + { + Name = name; + Flags = flags; + } + + /// + /// Initializes a new instance with the specified script access setting and script options. + /// + /// The script access setting for the target type member. + /// The script options for the target type member. + public ScriptMemberAttribute(ScriptAccess access, ScriptMemberFlags flags) + : base(access) + { + Flags = flags; + } + + /// + /// Initializes a new instance with the specified name, script access setting, and script options. + /// + /// The name that script code will use to access the target type member. + /// The script access setting for the target type member. + /// The script options for the target type member. + public ScriptMemberAttribute(string name, ScriptAccess access, ScriptMemberFlags flags) + : base(access) + { + Name = name; + Flags = flags; + } + + /// + /// Gets or sets the name that script code will use to access the target type member. + /// + /// + /// The default value is the name of the target type member. Note that this property has no + /// effect on the method binding algorithm. If a script-based call is bound to a method + /// that is exposed under a different name, it will be rejected even if an overload exists + /// that could receive the call. + /// + public string Name { get; set; } + + /// + /// Gets or sets the script options for the target type member. + /// + public ScriptMemberFlags Flags { get; set; } + } +} diff --git a/Unity/Package/Runtime/ScriptMemberAttribute.cs.meta b/Unity/Package/Runtime/ScriptMemberAttribute.cs.meta new file mode 100644 index 000000000..783420526 --- /dev/null +++ b/Unity/Package/Runtime/ScriptMemberAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75bb9cbd22b79df4b9ff08e8b5289b3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptMemberFlags.cs b/Unity/Package/Runtime/ScriptMemberFlags.cs new file mode 100644 index 000000000..cc1a3fc7f --- /dev/null +++ b/Unity/Package/Runtime/ScriptMemberFlags.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Defines options for exposing type members to script code. + /// + [Flags] + public enum ScriptMemberFlags + { + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that the field, property, or method return value is not to be restricted to + /// its declared type. + /// + ExposeRuntimeType = 0x00000001, + + /// + /// Specifies that the field, property, or method return value is to be marshaled with full + /// .NET type information even if it is null. Note that such a value will always + /// fail equality comparison with JavaScript's + /// null, + /// VBScript's + /// Nothing, + /// and other similar values. Instead, use or + /// to perform such a comparison. + /// + WrapNullResult = 0x00000002 + } +} diff --git a/Unity/Package/Runtime/ScriptMemberFlags.cs.meta b/Unity/Package/Runtime/ScriptMemberFlags.cs.meta new file mode 100644 index 000000000..d33b91798 --- /dev/null +++ b/Unity/Package/Runtime/ScriptMemberFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 31bcd1e230be24e43b7e28d59e368142 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptMethod.cs b/Unity/Package/Runtime/ScriptMethod.cs new file mode 100644 index 000000000..8f43cf870 --- /dev/null +++ b/Unity/Package/Runtime/ScriptMethod.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Globalization; +using System.Reflection; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript +{ + internal sealed class ScriptMethod : HostTarget, IReflect + { + private readonly ScriptItem target; + private readonly string name; + + public ScriptMethod(ScriptItem target, string name) + { + this.target = target; + this.name = name; + } + + public object Invoke(params object[] args) + { + return target.InvokeMethod(name, args); + } + + #region Object overrides + + public override string ToString() + { + return MiscHelpers.FormatInvariant("ScriptMethod:{0}", name); + } + + #endregion + + #region HostTarget overrides + + public override Type Type => typeof(void); + + public override object Target => this; + + public override object InvokeTarget => null; + + public override object DynamicInvokeTarget => null; + + public override HostTargetFlags GetFlags(IHostContext context) + { + return HostTargetFlags.None; + } + + public override bool TryInvoke(IHostContext context, BindingFlags invokeFlags, object[] args, object[] bindArgs, out object result) + { + result = target.InvokeMethod(name, args); + return true; + } + + public override Invocability GetInvocability(IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return Invocability.Delegate; + } + + #endregion + + #region IReflect implementation + + MethodInfo IReflect.GetMethod(string methodName, BindingFlags bindFlags, Binder binder, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + MethodInfo IReflect.GetMethod(string methodName, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + MethodInfo[] IReflect.GetMethods(BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + FieldInfo IReflect.GetField(string fieldName, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + FieldInfo[] IReflect.GetFields(BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + PropertyInfo IReflect.GetProperty(string propertyName, BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + PropertyInfo IReflect.GetProperty(string propertyName, BindingFlags bindFlags, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + PropertyInfo[] IReflect.GetProperties(BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + MemberInfo[] IReflect.GetMember(string memberName, BindingFlags bindFlags) + { + // This occurs during VB-based dynamic script item invocation. It was not observed + // before script items gained an IReflect/IExpando implementation that exposes + // script item properties as fields. Apparently VB's dynamic invocation support not + // only recognizes IReflect/IExpando but actually favors it over DynamicObject. + + return typeof(ScriptMethod).GetMember(MiscHelpers.EnsureNonBlank(memberName, "Invoke"), bindFlags); + } + + MemberInfo[] IReflect.GetMembers(BindingFlags bindFlags) + { + throw new NotImplementedException(); + } + + object IReflect.InvokeMember(string memberName, BindingFlags invokeFlags, Binder binder, object invokeTarget, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) + { + throw new NotImplementedException(); + } + + Type IReflect.UnderlyingSystemType => throw new NotImplementedException(); + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptMethod.cs.meta b/Unity/Package/Runtime/ScriptMethod.cs.meta new file mode 100644 index 000000000..b9e7545a2 --- /dev/null +++ b/Unity/Package/Runtime/ScriptMethod.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29e6c70e323c54c42ae0e7bcdc31d464 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptObject.cs b/Unity/Package/Runtime/ScriptObject.cs new file mode 100644 index 000000000..71bdae529 --- /dev/null +++ b/Unity/Package/Runtime/ScriptObject.cs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; +using System.Dynamic; + +namespace Microsoft.ClearScript +{ + /// + /// Provides the base implementation for all script objects. + /// + public abstract class ScriptObject : DynamicObject, IScriptObject + { + internal ScriptObject() + { + } + + #region IScriptObject implementation + + /// + public abstract ScriptEngine Engine { get; } + + /// + public abstract object GetProperty(string name, params object[] args); + + /// + public abstract void SetProperty(string name, params object[] args); + + /// + public abstract bool DeleteProperty(string name); + + /// + public abstract IEnumerable PropertyNames { get; } + + /// + public abstract object this[string name, params object[] args] { get; set; } + + /// + public abstract object GetProperty(int index); + + /// + public abstract void SetProperty(int index, object value); + + /// + public abstract bool DeleteProperty(int index); + + /// + public abstract IEnumerable PropertyIndices { get; } + + /// + public abstract object this[int index] { get; set; } + + /// + public abstract object Invoke(bool asConstructor, params object[] args); + + /// + public abstract object InvokeMethod(string name, params object[] args); + + /// + public object InvokeAsFunction(params object[] args) + { + return Invoke(false, args); + } + + #endregion + + #region IDisposable implementation + + /// + public abstract void Dispose(); + + #endregion + } +} diff --git a/Unity/Package/Runtime/ScriptObject.cs.meta b/Unity/Package/Runtime/ScriptObject.cs.meta new file mode 100644 index 000000000..20c8f3eb6 --- /dev/null +++ b/Unity/Package/Runtime/ScriptObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f12b1a74a436064a862fdc3707915ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ScriptUsageAttribute.cs b/Unity/Package/Runtime/ScriptUsageAttribute.cs new file mode 100644 index 000000000..bdb420549 --- /dev/null +++ b/Unity/Package/Runtime/ScriptUsageAttribute.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + /// + /// Specifies how the target type member is to be exposed to script code. + /// + /// + /// This attribute is applicable to events, fields, methods, properties, and nested types. + /// + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct)] + public class ScriptUsageAttribute : Attribute + { + /// + /// Initializes a new instance. + /// + public ScriptUsageAttribute() + { + } + + /// + /// Initializes a new instance with the specified script access setting. + /// + /// The script access setting for the target type member. + public ScriptUsageAttribute(ScriptAccess access) + { + Access = access; + } + + /// + /// Gets the script access setting for the target type member. + /// + public ScriptAccess Access { get; } + } +} diff --git a/Unity/Package/Runtime/ScriptUsageAttribute.cs.meta b/Unity/Package/Runtime/ScriptUsageAttribute.cs.meta new file mode 100644 index 000000000..c846ed7af --- /dev/null +++ b/Unity/Package/Runtime/ScriptUsageAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6b8682ee0b41d642b760427a942546b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/StringDocument.cs b/Unity/Package/Runtime/StringDocument.cs new file mode 100644 index 000000000..2fba246e8 --- /dev/null +++ b/Unity/Package/Runtime/StringDocument.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.IO; +using System.Text; + +namespace Microsoft.ClearScript +{ + /// + /// Provides an in-memory implementation for a text document. + /// + public class StringDocument : Document + { + /// + /// Initializes a new instance. + /// + /// A structure containing meta-information for the document. + /// A string containing the document's contents. + public StringDocument(DocumentInfo info, string contents) + { + Info = info; + StringContents = contents; + } + + /// + /// Gets the document's contents as a string. + /// + public string StringContents { get; } + + #region Document overrides + + /// + /// Gets a structure containing meta-information for the document. + /// + public override DocumentInfo Info { get; } + + /// + /// Gets a stream that provides read access to the document. + /// + /// + /// The implementation of this property returns a + /// instance. + /// + public override Stream Contents => new MemoryStream(Encoding.GetBytes(StringContents), false); + + /// + /// Gets the document's character encoding. + /// + /// + /// instances return for this property. + /// + public override Encoding Encoding => Encoding.UTF8; + + #endregion + } +} diff --git a/Unity/Package/Runtime/StringDocument.cs.meta b/Unity/Package/Runtime/StringDocument.cs.meta new file mode 100644 index 000000000..7407aeb23 --- /dev/null +++ b/Unity/Package/Runtime/StringDocument.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfd75421fba7fe249ad60609bb1eb965 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Undefined.cs b/Unity/Package/Runtime/Undefined.cs new file mode 100644 index 000000000..59799c330 --- /dev/null +++ b/Unity/Package/Runtime/Undefined.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Represents an undefined value. + /// + /// + /// Some script languages support one or more special non-null values that represent + /// nonexistent, missing, unknown, or undefined data. The ClearScript library maps such values + /// to an instance of this class. + /// + /// + public class Undefined + { + /// + /// The sole instance of the class. + /// + public static readonly Undefined Value = new Undefined(); + + private Undefined() + { + } + + #region Object overrides + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + /// + /// The version of this method returns "[undefined]". + /// + public override string ToString() + { + return "[undefined]"; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Undefined.cs.meta b/Unity/Package/Runtime/Undefined.cs.meta new file mode 100644 index 000000000..78a0bfabd --- /dev/null +++ b/Unity/Package/Runtime/Undefined.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8c3a406e4217984caefee5c804b7038 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/UniqueDocumentInfo.cs b/Unity/Package/Runtime/UniqueDocumentInfo.cs new file mode 100644 index 000000000..dc95f39cc --- /dev/null +++ b/Unity/Package/Runtime/UniqueDocumentInfo.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript +{ + internal class UniqueDocumentInfo + { + public UniqueDocumentInfo(DocumentInfo info, ulong uniqueId, string uniqueName) + { + Info = info; + UniqueId = uniqueId; + UniqueName = uniqueName; + } + + public DocumentInfo Info { get; } + + public string Name => Info.Name; + + public Uri Uri => Info.Uri; + + public Uri SourceMapUri => Info.SourceMapUri; + + public DocumentCategory Category => Info.Category; + + public DocumentFlags? Flags => Info.Flags; + + public DocumentContextCallback ContextCallback => Info.ContextCallback; + + public ulong UniqueId { get; } + + public string UniqueName { get; } + } +} diff --git a/Unity/Package/Runtime/UniqueDocumentInfo.cs.meta b/Unity/Package/Runtime/UniqueDocumentInfo.cs.meta new file mode 100644 index 000000000..2f3d36d40 --- /dev/null +++ b/Unity/Package/Runtime/UniqueDocumentInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62096dd2079a92f43b63c872a6b85847 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util.meta b/Unity/Package/Runtime/Util.meta new file mode 100644 index 000000000..4d6515977 --- /dev/null +++ b/Unity/Package/Runtime/Util.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa033c04d240fcf44b4798f3ac1ac413 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/ArrayHelpers.cs b/Unity/Package/Runtime/Util/ArrayHelpers.cs new file mode 100644 index 000000000..a4672793a --- /dev/null +++ b/Unity/Package/Runtime/Util/ArrayHelpers.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Linq; + +namespace Microsoft.ClearScript.Util +{ + internal static class ArrayHelpers + { + public static void Iterate(this Array array, Action action) + { + if (array.Rank > 0) + { + var dimensions = Enumerable.Range(0, array.Rank); + if (dimensions.Aggregate(1, (count, dimension) => count * array.GetLength(dimension)) > 0) + { + Iterate(array, new int[array.Rank], 0, action); + } + } + } + + private static void Iterate(Array array, int[] indices, int dimension, Action action) + { + if (dimension >= indices.Length) + { + action(indices); + } + else + { + var lowerBound = array.GetLowerBound(dimension); + var upperBound = array.GetUpperBound(dimension); + for (var index = lowerBound; index <= upperBound; index++) + { + indices[dimension] = index; + Iterate(array, indices, dimension + 1, action); + } + } + } + + public static T[] GetEmptyArray() + { + return EmptyArray.Value; + } + + #region Nested type: EmptyArray + + private static class EmptyArray + { + public static readonly T[] Value = new T[0]; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/ArrayHelpers.cs.meta b/Unity/Package/Runtime/Util/ArrayHelpers.cs.meta new file mode 100644 index 000000000..99d01d8b8 --- /dev/null +++ b/Unity/Package/Runtime/Util/ArrayHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6d7b4b9fc6aa844281f8f6094e2fd25 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs b/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs new file mode 100644 index 000000000..ca208720b --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class AssemblyHelpers + { + public static IEnumerable GetAllTypes(this Assembly assembly) + { + try + { + return assembly.GetTypes().Concat(assembly.GetForwardedTypes()); + } + catch (ReflectionTypeLoadException exception) + { + // ReSharper disable once RedundantEnumerableCastCall + return exception.Types.OfType(); + } + } + } +} diff --git a/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs.meta b/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs.meta new file mode 100644 index 000000000..f53ed1095 --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyHelpers.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed575b803463ff442a8ff467ed45dec6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/AssemblyHelpers.cs b/Unity/Package/Runtime/Util/AssemblyHelpers.cs new file mode 100644 index 000000000..72657d11b --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyHelpers.cs @@ -0,0 +1,253 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class AssemblyHelpers + { + public static string GetFullAssemblyName(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return name; + } + + if (MiscHelpers.Try(out var assembly, () => Assembly.Load(name))) + { + return assembly.FullName; + } + + var fileName = name; + if (!string.Equals(Path.GetExtension(fileName), ".dll", StringComparison.OrdinalIgnoreCase)) + { + fileName = Path.ChangeExtension(fileName + '.', "dll"); + } + + if (MiscHelpers.Try(out var assemblyName, () => AssemblyName.GetAssemblyName(fileName))) + { + return assemblyName.FullName; + } + + var dirPath = Path.GetDirectoryName(typeof(string).Assembly.Location); + if (!string.IsNullOrWhiteSpace(dirPath)) + { + // ReSharper disable AccessToModifiedClosure + + var path = Path.Combine(dirPath, fileName); + if (File.Exists(path) && MiscHelpers.Try(out assemblyName, () => AssemblyName.GetAssemblyName(path))) + { + return assemblyName.FullName; + } + + if (MiscHelpers.Try(out var subDirPaths, () => Directory.EnumerateDirectories(dirPath, "*", SearchOption.AllDirectories))) + { + foreach (var subDirPath in subDirPaths) + { + path = Path.Combine(subDirPath, fileName); + if (File.Exists(path) && MiscHelpers.Try(out assemblyName, () => AssemblyName.GetAssemblyName(path))) + { + return assemblyName.FullName; + } + } + } + + // ReSharper restore AccessToModifiedClosure + } + + return name; + } + + public static Assembly TryLoad(AssemblyName name) + { + if (MiscHelpers.Try(out var assembly, () => Assembly.Load(name))) + { + return assembly; + } + + return null; + } + + public static T GetOrLoadCustomAttribute(this Assembly assembly, IHostContext context, bool inherit = true) where T : Attribute + { + return CustomAttributes.GetOrLoad(context, assembly, inherit).SingleOrDefault(); + } + + public static IEnumerable GetOrLoadCustomAttributes(this Assembly assembly, IHostContext context, bool inherit = true) where T : Attribute + { + return CustomAttributes.GetOrLoad(context, assembly, inherit); + } + + public static bool HasCustomAttributes(this Assembly assembly, IHostContext context, bool inherit = true) where T : Attribute + { + return CustomAttributes.Has(context, assembly, inherit); + } + + public static bool IsFriendOf(this Assembly thisAssembly, IHostContext context, Assembly thatAssembly) + { + if (thatAssembly == thisAssembly) + { + return true; + } + + var thisName = thisAssembly.GetName(); + foreach (var attribute in thatAssembly.GetOrLoadCustomAttributes(context, false)) + { + var thatName = new AssemblyName(attribute.AssemblyName); + if (AssemblyName.ReferenceMatchesDefinition(thatName, thisName)) + { + return true; + } + } + + return false; + } + + public static IEnumerable GetReferencedEnums(this Assembly assembly) + { + var processedTypes = new HashSet(); + return assembly.GetAllTypes().SelectMany(type => GetReferencedEnums(assembly, type, processedTypes)); + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, Type type, HashSet processedTypes) + { + if ((type == null) || !type.IsVisible || type.ContainsGenericParameters || processedTypes.Contains(type)) + { + yield break; + } + + processedTypes.Add(type); + + if (type.IsEnum) + { + yield return type; + yield break; + } + + foreach (var enumType in GetReferencedEnums(assembly, type.GetElementType(), processedTypes)) + { + yield return enumType; + } + + foreach (var enumType in type.GetGenericArguments().SelectMany(argType => GetReferencedEnums(assembly, argType, processedTypes))) + { + yield return enumType; + } + + foreach (var enumType in GetReferencedEnums(assembly, type.BaseType, processedTypes)) + { + yield return enumType; + } + + foreach (var enumType in type.GetInterfaces().SelectMany(interfaceType => GetReferencedEnums(assembly, interfaceType, processedTypes))) + { + yield return enumType; + } + + if (type.Assembly == assembly) + { + foreach (var enumType in type.GetMembers().SelectMany(member => GetReferencedEnums(assembly, member, processedTypes))) + { + yield return enumType; + } + } + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, MemberInfo member, HashSet processedTypes) + { + if (member == null) + { + return Enumerable.Empty(); + } + + if (member.MemberType == MemberTypes.Field) + { + return GetReferencedEnums(assembly, (FieldInfo)member, processedTypes); + } + + if (member.MemberType == MemberTypes.Property) + { + return GetReferencedEnums(assembly, (PropertyInfo)member, processedTypes); + } + + if (member.MemberType == MemberTypes.Method) + { + return GetReferencedEnums(assembly, (MethodInfo)member, processedTypes); + } + + if (member.MemberType == MemberTypes.NestedType) + { + return GetReferencedEnums(assembly, (Type)member, processedTypes); + } + + return Enumerable.Empty(); + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, FieldInfo field, HashSet processedTypes) + { + if (field == null) + { + return Enumerable.Empty(); + } + + return GetReferencedEnums(assembly, field.FieldType, processedTypes); + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, PropertyInfo property, HashSet processedTypes) + { + if (property == null) + { + yield break; + } + + foreach (var enumType in GetReferencedEnums(assembly, property.PropertyType, processedTypes)) + { + yield return enumType; + } + + foreach (var enumType in GetReferencedEnums(assembly, property.GetMethod, processedTypes)) + { + yield return enumType; + } + + foreach (var enumType in GetReferencedEnums(assembly, property.SetMethod, processedTypes)) + { + yield return enumType; + } + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, MethodInfo method, HashSet processedTypes) + { + if (method == null) + { + yield break; + } + + foreach (var enumType in GetReferencedEnums(assembly, method.ReturnParameter, processedTypes)) + { + yield return enumType; + } + + foreach (var enumType in method.GetParameters().SelectMany(param => GetReferencedEnums(assembly, param, processedTypes))) + { + yield return enumType; + } + } + + private static IEnumerable GetReferencedEnums(Assembly assembly, ParameterInfo param, HashSet processedTypes) + { + if (param == null) + { + return Enumerable.Empty(); + } + + return GetReferencedEnums(assembly, param.ParameterType, processedTypes); + } + } +} diff --git a/Unity/Package/Runtime/Util/AssemblyHelpers.cs.meta b/Unity/Package/Runtime/Util/AssemblyHelpers.cs.meta new file mode 100644 index 000000000..c3596c385 --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a40b8267612a09442ae24ec79271cb7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs b/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs new file mode 100644 index 000000000..cf8ac9604 --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal static class AssemblyTable + { + public static string GetFullAssemblyName(string name) + { + return AssemblyHelpers.GetFullAssemblyName(name); + } + } +} diff --git a/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs.meta b/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs.meta new file mode 100644 index 000000000..0bdea0e7c --- /dev/null +++ b/Unity/Package/Runtime/Util/AssemblyTable.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 895428b58fb127747af5ef841d449d4c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/BitwiseHelpers.cs b/Unity/Package/Runtime/Util/BitwiseHelpers.cs new file mode 100644 index 000000000..2ac52960b --- /dev/null +++ b/Unity/Package/Runtime/Util/BitwiseHelpers.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Net; + +namespace Microsoft.ClearScript.Util +{ + internal static class BitwiseHelpers + { + #region bitwise operations + + public static byte And(this byte value, byte mask) + { + var tempValue = value; + tempValue &= mask; + return tempValue; + } + + public static byte Or(this byte value, byte mask) + { + var tempValue = value; + tempValue |= mask; + return tempValue; + } + + public static byte Xor(this byte value, byte mask) + { + var tempValue = value; + tempValue ^= mask; + return tempValue; + } + + public static bool Has(this byte value, byte mask) + { + return value.And(mask) != 0; + } + + public static bool HasAll(this byte value, byte mask) + { + return value.And(mask) == mask; + } + + #endregion + + #region signed/unsigned conversion + + public static short ToSigned(this ushort value) + { + return BitConverter.ToInt16(BitConverter.GetBytes(value), 0); + } + + public static int ToSigned(this uint value) + { + return BitConverter.ToInt32(BitConverter.GetBytes(value), 0); + } + + public static long ToSigned(this ulong value) + { + return BitConverter.ToInt64(BitConverter.GetBytes(value), 0); + } + + public static ushort ToUnsigned(this short value) + { + return BitConverter.ToUInt16(BitConverter.GetBytes(value), 0); + } + + public static uint ToUnsigned(this int value) + { + return BitConverter.ToUInt32(BitConverter.GetBytes(value), 0); + } + + public static ulong ToUnsigned(this long value) + { + return BitConverter.ToUInt64(BitConverter.GetBytes(value), 0); + } + + #endregion + + #region network byte order support + + public static ushort ToHostUInt16(this byte[] bytes, int index = 0) + { + return IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, index)).ToUnsigned(); + } + + public static uint ToHostUInt32(this byte[] bytes, int index = 0) + { + return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, index)).ToUnsigned(); + } + + public static ulong ToHostUInt64(this byte[] bytes, int index = 0) + { + return IPAddress.NetworkToHostOrder(BitConverter.ToInt64(bytes, index)).ToUnsigned(); + } + + public static byte[] ToNetworkBytes(this ushort value) + { + return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value.ToSigned())); + } + + public static byte[] ToNetworkBytes(this uint value) + { + return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value.ToSigned())); + } + + public static byte[] ToNetworkBytes(this ulong value) + { + return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value.ToSigned())); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/BitwiseHelpers.cs.meta b/Unity/Package/Runtime/Util/BitwiseHelpers.cs.meta new file mode 100644 index 000000000..8c1b01a55 --- /dev/null +++ b/Unity/Package/Runtime/Util/BitwiseHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3bee896c0f423254a985aef6620d416b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM.meta b/Unity/Package/Runtime/Util/COM.meta new file mode 100644 index 000000000..2addf3942 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41d4382c00c9404419f1cab2a70d4b87 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs b/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs new file mode 100644 index 000000000..dcd21c60b --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class ActivationHelpers + { + public static IntPtr CreateInstance(string progID) + { + var clsid = CLSIDFromProgID(progID); + var iid = typeof(T).GUID; + HResult.Check(NativeMethods.CoCreateInstance(ref clsid, IntPtr.Zero, 1, ref iid, out var pInterface)); + return pInterface; + } + + private static Guid CLSIDFromProgID(string progID) + { + if (!Guid.TryParseExact(progID, "B", out var clsid)) + { + HResult.Check(NativeMethods.CLSIDFromProgID(progID, out clsid)); + } + + return clsid; + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs.meta new file mode 100644 index 000000000..a1a6523e9 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/ActivationHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f041cfde208d614e9a0da16d58dba05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/Dispatch.cs b/Unity/Package/Runtime/Util/COM/Dispatch.cs new file mode 100644 index 000000000..dc33f4111 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/Dispatch.cs @@ -0,0 +1,218 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using DISPPARAMS = System.Runtime.InteropServices.ComTypes.DISPPARAMS; +using EXCEPINFO = System.Runtime.InteropServices.ComTypes.EXCEPINFO; + +namespace Microsoft.ClearScript.Util.COM +{ + #region enums + + [Flags] + internal enum DispatchFlags : ushort + { + Method = 0x1, + PropertyGet = 0x2, + PropertyPut = 0x4, + PropertyPutRef = 0x8, + Construct = 0x4000 + } + + [Flags] + internal enum DispatchNameFlags : uint + { + CaseSensitive = 0x00000001, + Ensure = 0x00000002, + Implicit = 0x00000004, + CaseInsensitive = 0x00000008, + Internal = 0x00000010, + NoDynamicProperties = 0x00000020 + } + + [Flags] + internal enum DispatchPropFlags : uint + { + CanGet = 0x00000001, + CannotGet = 0x00000002, + CanPut = 0x00000004, + CannotPut = 0x00000008, + CanPutRef = 0x00000010, + CannotPutRef = 0x00000020, + NoSideEffects = 0x00000040, + DynamicType = 0x00000080, + CanCall = 0x00000100, + CannotCall = 0x00000200, + CanConstruct = 0x00000400, + CannotConstruct = 0x00000800, + CanSourceEvents = 0x00001000, + CannotSourceEvents = 0x00002000, + CanAll = CanGet | CanPut | CanPutRef | CanCall | CanConstruct | CanSourceEvents, + CannotAll = CannotGet | CannotPut | CannotPutRef | CannotCall | CannotConstruct | CannotSourceEvents, + ExtraAll = NoSideEffects | DynamicType, + All = CanAll | CannotAll | ExtraAll + } + + [Flags] + internal enum DispatchEnumFlags : uint + { + Default = 0x00000001, + All = 0x00000002 + } + + #endregion + + #region interfaces + + [ComImport] + [Guid("00020400-0000-0000-c000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IDispatch + { + [PreserveSig] + int GetTypeInfoCount( + [Out] out uint count + ); + + [PreserveSig] + int GetTypeInfo( + [In] uint index, + [In] int lcid, + [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo + ); + + [PreserveSig] + int GetIDsOfNames( + [In] ref Guid iid, + [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names, + [In] uint count, + [In] int lcid, + [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] int[] dispids + ); + + [PreserveSig] + int Invoke( + [In] int dispid, + [In] ref Guid iid, + [In] int lcid, + [In] DispatchFlags flags, + [In] ref DISPPARAMS args, + [In] IntPtr pVarResult, + [Out] out EXCEPINFO excepInfo, + [Out] out uint argErr + ); + } + + [ComImport] + [Guid("a6ef9860-c720-11d0-9337-00a0c90dcaa9")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IDispatchEx // : IDispatch + { + #region IDispatch members + + [PreserveSig] + int GetTypeInfoCount( + [Out] out uint count + ); + + [PreserveSig] + int GetTypeInfo( + [In] uint index, + [In] int lcid, + [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo + ); + + [PreserveSig] + int GetIDsOfNames( + [In] ref Guid iid, + [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names, + [In] uint count, + [In] int lcid, + [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] int[] dispids + ); + + [PreserveSig] + int Invoke( + [In] int dispid, + [In] ref Guid iid, + [In] int lcid, + [In] DispatchFlags flags, + [In] ref DISPPARAMS args, + [In] IntPtr pVarResult, + [Out] out EXCEPINFO excepInfo, + [Out] out uint argErr + ); + + #endregion + + [PreserveSig] + int GetDispID( + [In] [MarshalAs(UnmanagedType.BStr)] string name, + [In] DispatchNameFlags flags, + [Out] out int dispid + ); + + [PreserveSig] + int InvokeEx( + [In] int dispid, + [In] int lcid, + [In] DispatchFlags flags, + [In] ref DISPPARAMS args, + [In] IntPtr pVarResult, + [Out] out EXCEPINFO excepInfo, + [In] [Optional] [MarshalAs(UnmanagedType.Interface)] IServiceProvider svpCaller + ); + + [PreserveSig] + int DeleteMemberByName( + [In] [MarshalAs(UnmanagedType.BStr)] string name, + [In] DispatchNameFlags flags + ); + + [PreserveSig] + int DeleteMemberByDispID( + [In] int dispid + ); + + [PreserveSig] + int GetMemberProperties( + [In] int dispid, + [In] DispatchPropFlags fetchFlags, + [Out] out DispatchPropFlags flags + ); + + [PreserveSig] + int GetMemberName( + [In] int dispid, + [Out] [MarshalAs(UnmanagedType.BStr)] out string name + ); + + [PreserveSig] + int GetNextDispID( + [In] DispatchEnumFlags flags, + [In] int dispidCurrent, + [Out] out int dispidNext + ); + + [PreserveSig] + int GetNameSpaceParent( + [Out] [MarshalAs(UnmanagedType.IUnknown)] out object parent + ); + } + + [ComImport] + [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IServiceProvider + { + void QueryService( + [In] ref Guid guidService, + [In] ref Guid iid, + [Out] [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1)] out object service + ); + } + + #endregion +} diff --git a/Unity/Package/Runtime/Util/COM/Dispatch.cs.meta b/Unity/Package/Runtime/Util/COM/Dispatch.cs.meta new file mode 100644 index 000000000..33f59200d --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/Dispatch.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f8777929fc0b4d6418d71c4da89075bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs b/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs new file mode 100644 index 000000000..e1f2a2f2a --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs @@ -0,0 +1,335 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using DISPPARAMS = System.Runtime.InteropServices.ComTypes.DISPPARAMS; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class DispatchHelpers + { + private static Guid iid = Guid.Empty; + + public static readonly int VariantSize = sizeof(ushort) * 4 + IntPtr.Size * 2; + + public static ITypeInfo GetTypeInfo(this IDispatch dispatch) + { + if (HResult.Succeeded(dispatch.GetTypeInfoCount(out var count)) && (count > 0)) + { + if (HResult.Succeeded(dispatch.GetTypeInfo(0, 0, out var typeInfo))) + { + return typeInfo; + } + } + + return null; + } + + public static object GetProperty(this IDispatch dispatch, string name, params object[] args) + { + if (!MiscHelpers.Try(out int dispid, () => dispatch.GetDispIDForName(name))) + { + return Nonexistent.Value; + } + + using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatch.Invoke(dispid, ref iid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out _, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static void SetProperty(this IDispatch dispatch, string name, params object[] args) + { + if (args.Length < 1) + { + throw new ArgumentException("Invalid argument count", nameof(args)); + } + + var dispid = dispatch.GetDispIDForName(name); + using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args)) + { + using (var namedArgDispidBlock = new CoTaskMemBlock(sizeof(int))) + { + Marshal.WriteInt32(namedArgDispidBlock.Addr, SpecialDispIDs.PropertyPut); + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 1, rgdispidNamedArgs = namedArgDispidBlock.Addr }; + + var result = dispatch.Invoke(dispid, ref iid, 0, DispatchFlags.PropertyPut | DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out _, out _); + if (result == HResult.DISP_E_MEMBERNOTFOUND) + { + // VBScript objects can be finicky about property-put dispatch flags + + result = dispatch.Invoke(dispid, iid, 0, DispatchFlags.PropertyPut, ref dispArgs, IntPtr.Zero, out _, out _); + if (result == HResult.DISP_E_MEMBERNOTFOUND) + { + result = dispatch.Invoke(dispid, iid, 0, DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out _, out _); + } + } + + HResult.Check(result); + } + } + } + + public static IEnumerable GetPropertyNames(this IDispatch dispatch) + { + return dispatch.GetMembers().Select(member => member.Name); + } + + public static object Invoke(this IDispatch dispatch, params object[] args) + { + using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatch.Invoke(SpecialDispIDs.Default, ref iid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static object InvokeMethod(this IDispatch dispatch, string name, params object[] args) + { + var dispid = dispatch.GetDispIDForName(name); + if (dispid == SpecialDispIDs.GetEnumerator) + { + return dispatch.GetProperty(SpecialMemberNames.NewEnum, args); + } + + using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatch.Invoke(dispid, iid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static IEnumerable GetMembers(this IDispatch dispatch) + { + // ReSharper disable once RedundantEnumerableCastCall + return dispatch.GetMembersRaw().GroupBy(member => member.DispID, DispatchMember.Merge).OfType(); + } + + private static int GetDispIDForName(this IDispatch dispatch, string name) + { + var dispids = new int[1]; + var names = new[] { name }; + if (HResult.Succeeded(dispatch.GetIDsOfNames(ref iid, names, 1, 0, dispids))) + { + return dispids[0]; + } + + if (name.IsDispIDName(out dispids[0])) + { + return dispids[0]; + } + + var member = dispatch.GetMembers().FirstOrDefault(testMember => testMember.Name == name); + if (member == null) + { + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no property named '{0}'", name)); + } + + return member.DispID; + } + + private static IEnumerable GetMembersRaw(this IDispatch dispatch) + { + var typeInfo = dispatch.GetTypeInfo(); + if (typeInfo == null) + { + throw new NotSupportedException("The object does not support late binding"); + } + + return typeInfo.GetDispatchMembers(); + } + } + + internal static class DispatchExHelpers + { + public static ITypeInfo GetTypeInfo(this IDispatchEx dispatchEx) + { + if (HResult.Succeeded(dispatchEx.GetTypeInfoCount(out var count)) && (count > 0)) + { + if (HResult.Succeeded(dispatchEx.GetTypeInfo(0, 0, out var typeInfo))) + { + return typeInfo; + } + } + + return null; + } + + public static object GetProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args) + { + if (!MiscHelpers.Try(out int dispid, () => dispatchEx.GetDispIDForName(name, false, ignoreCase))) + { + return Nonexistent.Value; + } + + using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static void SetProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args) + { + if (args.Length < 1) + { + throw new ArgumentException("Invalid argument count", nameof(args)); + } + + var dispid = dispatchEx.GetDispIDForName(name, true, ignoreCase); + using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args)) + { + using (var namedArgDispidBlock = new CoTaskMemBlock(sizeof(int))) + { + Marshal.WriteInt32(namedArgDispidBlock.Addr, SpecialDispIDs.PropertyPut); + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 1, rgdispidNamedArgs = namedArgDispidBlock.Addr }; + + var result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut | DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out _); + if (result == HResult.DISP_E_MEMBERNOTFOUND) + { + // VBScript objects can be finicky about property-put dispatch flags + + result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut, ref dispArgs, IntPtr.Zero, out _); + if (result == HResult.DISP_E_MEMBERNOTFOUND) + { + result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out _); + } + } + + HResult.Check(result); + } + } + } + + public static bool DeleteProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase) + { + return dispatchEx.DeleteMemberByName(name, ignoreCase ? DispatchNameFlags.CaseInsensitive : DispatchNameFlags.CaseSensitive) == HResult.S_OK; + } + + public static IEnumerable GetPropertyNames(this IDispatchEx dispatchEx) + { + return dispatchEx.GetMembers().Select(member => member.Name); + } + + public static object Invoke(this IDispatchEx dispatchEx, bool asConstructor, params object[] args) + { + using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, asConstructor ? DispatchFlags.Construct : DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static object InvokeMethod(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args) + { + var dispid = dispatchEx.GetDispIDForName(name, false, ignoreCase); + if (dispid == SpecialDispIDs.GetEnumerator) + { + return dispatchEx.GetProperty(SpecialMemberNames.NewEnum, ignoreCase, args); + } + + using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args)) + { + using (var resultVariantBlock = new CoTaskMemVariantBlock()) + { + var dispArgs = new DISPPARAMS { cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero }; + HResult.Check(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _)); + return MiscHelpers.GetObjectForVariant(resultVariantBlock.Addr); + } + } + } + + public static IEnumerable GetMembers(this IDispatchEx dispatchEx) + { + // ReSharper disable once RedundantEnumerableCastCall + return dispatchEx.GetMembersRaw().GroupBy(member => member.DispID, DispatchMember.Merge).OfType(); + } + + private static int GetDispIDForName(this IDispatchEx dispatchEx, string name, bool ensure, bool ignoreCase) + { + var flags = ignoreCase ? DispatchNameFlags.CaseInsensitive : DispatchNameFlags.CaseSensitive; + if (ensure) + { + flags |= DispatchNameFlags.Ensure; + } + + var result = dispatchEx.GetDispID(name, flags, out var dispid); + if (ensure && (result == HResult.DISP_E_UNKNOWNNAME)) + { + throw new NotSupportedException("The object does not support dynamic properties"); + } + + if (HResult.Succeeded(result)) + { + return dispid; + } + + if (name.IsDispIDName(out dispid)) + { + return dispid; + } + + var member = dispatchEx.GetMembers().FirstOrDefault(testMember => testMember.Name.Equals(name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); + if (member != null) + { + return member.DispID; + } + + throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no property named '{0}'", name)); + } + + private static IEnumerable GetMembersRaw(this IDispatchEx dispatchEx) + { + var isEnumerable = false; + + var result = dispatchEx.GetNextDispID(DispatchEnumFlags.All, SpecialDispIDs.StartEnum, out var dispid); + while (result == HResult.S_OK) + { + if (HResult.Succeeded(dispatchEx.GetMemberName(dispid, out var name))) + { + if (HResult.Succeeded(dispatchEx.GetMemberProperties(dispid, DispatchPropFlags.CanAll, out var flags))) + { + if (dispid == SpecialDispIDs.NewEnum) + { + isEnumerable = true; + } + + yield return new DispatchMember(name, dispid, flags); + } + } + + result = dispatchEx.GetNextDispID(DispatchEnumFlags.All, dispid, out dispid); + } + + if (isEnumerable) + { + yield return new DispatchMember("GetEnumerator", SpecialDispIDs.GetEnumerator, DispatchPropFlags.CanCall); + } + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs.meta new file mode 100644 index 000000000..388b616b2 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0ee2188110d06845868061e2485c5f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/DispatchMember.cs b/Unity/Package/Runtime/Util/COM/DispatchMember.cs new file mode 100644 index 000000000..8263b203c --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchMember.cs @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices.ComTypes; + +namespace Microsoft.ClearScript.Util.COM +{ + internal sealed class DispatchMember + { + public string Name { get; } + + public int DispID { get; } + + public DispatchFlags DispatchFlags { get; private set; } + + private DispatchMember(string name, int dispid) + { + Name = name; + DispID = dispid; + } + + public DispatchMember(string name, int dispid, INVOKEKIND invokeKind) + : this(name, dispid) + { + if (invokeKind.HasFlag(INVOKEKIND.INVOKE_FUNC)) + { + DispatchFlags |= DispatchFlags.Method; + } + + if (invokeKind.HasFlag(INVOKEKIND.INVOKE_PROPERTYGET)) + { + DispatchFlags |= DispatchFlags.PropertyGet; + } + + if (invokeKind.HasFlag(INVOKEKIND.INVOKE_PROPERTYPUT)) + { + DispatchFlags |= DispatchFlags.PropertyPut; + } + + if (invokeKind.HasFlag(INVOKEKIND.INVOKE_PROPERTYPUTREF)) + { + DispatchFlags |= DispatchFlags.PropertyPutRef; + } + } + + public DispatchMember(string name, int dispid, DispatchPropFlags flags) + : this(name, dispid) + { + if (flags.HasFlag(DispatchPropFlags.CanCall)) + { + DispatchFlags |= DispatchFlags.Method; + } + + if (flags.HasFlag(DispatchPropFlags.CanGet)) + { + DispatchFlags |= DispatchFlags.PropertyGet; + } + + if (flags.HasFlag(DispatchPropFlags.CanPut)) + { + DispatchFlags |= DispatchFlags.PropertyPut; + } + + if (flags.HasFlag(DispatchPropFlags.CanPutRef)) + { + DispatchFlags |= DispatchFlags.PropertyPutRef; + } + } + + public static DispatchMember Merge(int dispid, IEnumerable group) + { + var members = group.ToArray(); + if (members.Length < 1) + { + return null; + } + + var result = new DispatchMember(members[0].Name, dispid); + foreach (var member in members) + { + Debug.Assert(member.Name == result.Name); + Debug.Assert(member.DispID == result.DispID); + result.DispatchFlags |= member.DispatchFlags; + } + + return result; + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/DispatchMember.cs.meta b/Unity/Package/Runtime/Util/COM/DispatchMember.cs.meta new file mode 100644 index 000000000..2d0fea030 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchMember.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d18b31e731d33234eb2a026ea1f79903 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs b/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs new file mode 100644 index 000000000..8e592406c --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs @@ -0,0 +1,229 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Microsoft.ClearScript.Util.COM +{ + internal sealed class DynamicDispatchWrapper : IDynamic + { + private readonly HostItem hostItem; + private readonly IDispatch dispatch; + private IReadOnlyList members; + + public DynamicDispatchWrapper(HostItem hostItem, IDispatch dispatch) + { + this.hostItem = hostItem; + this.dispatch = dispatch; + } + + private IReadOnlyList GetMembers() + { + return members ?? (members = dispatch.GetMembers().ToArray()); + } + + public object GetProperty(string name, params object[] args) + { + return GetProperty(name, out _, args); + } + + public object GetProperty(string name, out bool isCacheable, params object[] args) + { + isCacheable = false; + + DispatchMember member = null; + if (args.Length < 1) + { + // some objects crash on attempt to retrieve a method as a property + + member = GetMembers().FirstOrDefault(testMember => testMember.Name == name); + if ((member != null) && member.DispatchFlags == DispatchFlags.Method) + { + return new HostMethod(hostItem, name); + } + } + + try + { + var result = dispatch.GetProperty(name, args); + return result; + } + catch + { + if (args.Length < 1) + { + if (member == null) + { + member = GetMembers().FirstOrDefault(testMember => testMember.Name == name); + } + + if ((member != null) && !member.DispatchFlags.HasFlag(DispatchFlags.Method)) + { + return new HostIndexedProperty(hostItem, name); + } + + return new HostMethod(hostItem, name); + } + + throw; + } + } + + public void SetProperty(string name, params object[] args) + { + dispatch.SetProperty(name, args); + } + + public bool DeleteProperty(string name) + { + throw new NotSupportedException("The object does not support dynamic properties"); + } + + public string[] GetPropertyNames() + { + return GetMembers().Select(member => member.Name).ExcludeIndices().ToArray(); + } + + public object GetProperty(int index) + { + return dispatch.GetProperty(index.ToString(CultureInfo.InvariantCulture)); + } + + public void SetProperty(int index, object value) + { + dispatch.SetProperty(index.ToString(CultureInfo.InvariantCulture), value); + } + + public bool DeleteProperty(int index) + { + throw new NotSupportedException("The object does not support dynamic properties"); + } + + public int[] GetPropertyIndices() + { + return GetMembers().Select(member => member.Name).GetIndices().ToArray(); + } + + public object Invoke(bool asConstructor, params object[] args) + { + if (asConstructor) + { + throw new NotSupportedException("The object does not support constructor invocation"); + } + + return dispatch.Invoke(args); + } + + public object InvokeMethod(string name, params object[] args) + { + return dispatch.InvokeMethod(name, args); + } + } + + internal sealed class DynamicDispatchExWrapper : IDynamic + { + private readonly HostItem hostItem; + private readonly IDispatchEx dispatchEx; + + public DynamicDispatchExWrapper(HostItem hostItem, IDispatchEx dispatchEx) + { + this.hostItem = hostItem; + this.dispatchEx = dispatchEx; + } + + public object GetProperty(string name, params object[] args) + { + return GetProperty(name, out _, args); + } + + public object GetProperty(string name, out bool isCacheable, params object[] args) + { + isCacheable = false; + + DispatchMember member = null; + if (args.Length < 1) + { + // some objects crash on attempt to retrieve a method as a property + + member = dispatchEx.GetMembers().FirstOrDefault(testMember => testMember.Name == name); + if ((member != null) && member.DispatchFlags == DispatchFlags.Method) + { + return new HostMethod(hostItem, name); + } + } + + try + { + var result = dispatchEx.GetProperty(name, false, args); + return result; + } + catch + { + if (args.Length < 1) + { + if (member == null) + { + member = dispatchEx.GetMembers().FirstOrDefault(testMember => testMember.Name == name); + } + + if ((member != null) && !member.DispatchFlags.HasFlag(DispatchFlags.Method)) + { + return new HostIndexedProperty(hostItem, name); + } + + return new HostMethod(hostItem, name); + } + + throw; + } + } + + public void SetProperty(string name, params object[] args) + { + dispatchEx.SetProperty(name, false, args); + } + + public bool DeleteProperty(string name) + { + return dispatchEx.DeleteProperty(name, false); + } + + public string[] GetPropertyNames() + { + return dispatchEx.GetPropertyNames().ExcludeIndices().ToArray(); + } + + public object GetProperty(int index) + { + return dispatchEx.GetProperty(index.ToString(CultureInfo.InvariantCulture), false); + } + + public void SetProperty(int index, object value) + { + dispatchEx.SetProperty(index.ToString(CultureInfo.InvariantCulture), false, value); + } + + public bool DeleteProperty(int index) + { + return dispatchEx.DeleteProperty(index.ToString(CultureInfo.InvariantCulture), false); + } + + public int[] GetPropertyIndices() + { + return dispatchEx.GetPropertyNames().GetIndices().ToArray(); + } + + public object Invoke(bool asConstructor, params object[] args) + { + return dispatchEx.Invoke(asConstructor, args); + } + + public object InvokeMethod(string name, params object[] args) + { + return dispatchEx.InvokeMethod(name, false, args); + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs.meta b/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs.meta new file mode 100644 index 000000000..402979310 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/DispatchWrappers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c7ea3214fe8104449101caa2decad08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/HResult.cs b/Unity/Package/Runtime/Util/COM/HResult.cs new file mode 100644 index 000000000..75b6ccd3c --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/HResult.cs @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class HResult + { + // ReSharper disable InconsistentNaming + + public const int SEVERITY_SUCCESS = 0; + public const int SEVERITY_ERROR = 1; + + public const int FACILITY_NULL = 0; + public const int FACILITY_RPC = 1; + public const int FACILITY_DISPATCH = 2; + public const int FACILITY_STORAGE = 3; + public const int FACILITY_ITF = 4; + public const int FACILITY_WIN32 = 7; + public const int FACILITY_WINDOWS = 8; + public const int FACILITY_CONTROL = 10; + public const int FACILITY_INTERNET = 12; + public const int FACILITY_URT = 19; + + public const int S_OK = 0; + public const int S_FALSE = 1; + + public static readonly int E_NOINTERFACE = 0x80004002U.ToSigned(); + public static readonly int E_ABORT = 0x80004004U.ToSigned(); + public static readonly int E_FAIL = 0x80004005U.ToSigned(); + public static readonly int E_INVALIDARG = 0x80070057U.ToSigned(); + + public static readonly int CO_E_CLASSSTRING = 0x800401F3U.ToSigned(); + public static readonly int REGDB_E_CLASSNOTREG = 0x80040154U.ToSigned(); + + public static readonly int DISP_E_MEMBERNOTFOUND = 0x80020003U.ToSigned(); + public static readonly int DISP_E_UNKNOWNNAME = 0x80020006U.ToSigned(); + public static readonly int DISP_E_EXCEPTION = 0x80020009U.ToSigned(); + public static readonly int DISP_E_BADPARAMCOUNT = 0x8002000EU.ToSigned(); + public static readonly int SCRIPT_E_REPORTED = 0x80020101U.ToSigned(); + + public static readonly int CLEARSCRIPT_E_HOSTEXCEPTION = MakeResult(SEVERITY_ERROR, FACILITY_URT, 0xBAFF); + public static readonly int CLEARSCRIPT_E_SCRIPTITEMEXCEPTION = MakeResult(SEVERITY_ERROR, FACILITY_URT, 0xB0FF); + + public const int ERROR_FILE_EXISTS = 80; + public static readonly int WIN32_E_FILEEXISTS = MakeResult(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_EXISTS); + + // ReSharper restore InconsistentNaming + + public static void Check(uint result) + { + Check(result.ToSigned()); + } + + public static void Check(int result) + { + if (Succeeded(result) || !MiscHelpers.Try(out var exception, () => Marshal.GetExceptionForHR(result))) + { + return; + } + + if (exception.HResult != result) + { + // WORKAROUND: In some .NET test environments, Marshal.GetExceptionForHR sometimes + // converts COM error codes into unrelated exceptions that break critical features + // such as double execution prevention (see BugFix_DoubleExecution_JScript et al). + + if (result == SCRIPT_E_REPORTED) + { + throw new COMException("A script error has been reported", result); + } + + if (result == CLEARSCRIPT_E_HOSTEXCEPTION) + { + throw new COMException("A host exception has been reported", result); + } + } + + throw exception; + } + + public static bool Succeeded(uint result) + { + return GetSeverity(result) == SEVERITY_SUCCESS; + } + + public static bool Succeeded(int result) + { + return GetSeverity(result) == SEVERITY_SUCCESS; + } + + public static int GetSeverity(uint result) + { + return GetSeverity(result.ToSigned()); + } + + public static int GetSeverity(int result) + { + return (result >> 31) & 0x1; + } + + public static int GetFacility(uint result) + { + return GetFacility(result.ToSigned()); + } + + public static int GetFacility(int result) + { + return (result >> 16) & 0x1FFF; + } + + public static int GetCode(uint result) + { + return GetCode(result.ToSigned()); + } + + public static int GetCode(int result) + { + return result & 0xFFFF; + } + + public static int MakeResult(int severity, int facility, int code) + { + return ((uint)(code & 0xFFFF) | ((uint)(facility & 0x1FFF) << 16) | ((uint)(severity & 0x1) << 31)).ToSigned(); + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/HResult.cs.meta b/Unity/Package/Runtime/Util/COM/HResult.cs.meta new file mode 100644 index 000000000..f993d0442 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/HResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bd1acade2aff094d9457fdad80a5b07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/StructHelpers.cs b/Unity/Package/Runtime/Util/COM/StructHelpers.cs new file mode 100644 index 000000000..8b7279f17 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/StructHelpers.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class StructHelpers + { + public delegate void GetStruct(out IntPtr pStruct); + + public delegate void ReleaseStruct(IntPtr pStruct); + + public static IScope CreateScope(GetStruct get, ReleaseStruct release) + { + get(out var pStruct); + return Scope.Create(() => (T)Marshal.PtrToStructure(pStruct, typeof(T)), value => release(pStruct)); + } + + public static IEnumerable GetStructsFromArray(IntPtr pStructs, int count) + { + var size = Marshal.SizeOf(typeof(T)); + for (var pStruct = pStructs; count > 0; count--) + { + yield return (T)Marshal.PtrToStructure(pStruct, typeof(T)); + pStruct += size; + } + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/StructHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/StructHelpers.cs.meta new file mode 100644 index 000000000..2d61c35de --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/StructHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44d5d5f0683630b4792b05cb52541708 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs new file mode 100644 index 000000000..52797d962 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices.ComTypes; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static partial class TypeInfoHelpers + { + public static Type GetManagedType(this ITypeInfo typeInfo) + { + return null; + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs.meta b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs.meta new file mode 100644 index 000000000..db89dd392 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07ae75dd428f71b4c94ad49dcbc315d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs new file mode 100644 index 000000000..ff765436b --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs @@ -0,0 +1,185 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using FUNCDESC = System.Runtime.InteropServices.ComTypes.FUNCDESC; +using FUNCFLAGS = System.Runtime.InteropServices.ComTypes.FUNCFLAGS; +using INVOKEKIND = System.Runtime.InteropServices.ComTypes.INVOKEKIND; +using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR; +using TYPEFLAGS = System.Runtime.InteropServices.ComTypes.TYPEFLAGS; +using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND; +using VARDESC = System.Runtime.InteropServices.ComTypes.VARDESC; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static partial class TypeInfoHelpers + { + // GUID_ManagedName (um\cor.h) + private static readonly Guid managedNameGuid = new Guid("{0f21f359-ab84-41e8-9a78-36d110e6d2f9}"); + + public static ITypeLib GetContainingTypeLib(this ITypeInfo typeInfo) + { + return typeInfo.GetContainingTypeLib(out _); + } + + public static ITypeLib GetContainingTypeLib(this ITypeInfo typeInfo, out int index) + { + typeInfo.GetContainingTypeLib(out var typeLib, out index); + return typeLib; + } + + public static string GetName(this ITypeInfo typeInfo) + { + return typeInfo.GetMemberName(-1); + } + + public static string GetManagedName(this ITypeInfo typeInfo) + { + if (typeInfo is ITypeInfo2 typeInfo2) + { + // ReSharper disable EmptyGeneralCatchClause + + try + { + var guid = managedNameGuid; + typeInfo2.GetCustData(ref guid, out var data); + + if (data is string name) + { + return name.Trim(); + } + } + catch + { + } + + // ReSharper restore EmptyGeneralCatchClause + } + + return typeInfo.GetContainingTypeLib().GetManagedName() + "." + Marshal.GetTypeInfoName(typeInfo); + } + + public static string GetMemberName(this ITypeInfo typeInfo, int memid) + { + typeInfo.GetDocumentation(memid, out var name, out _, out _, out _); + return name; + } + + public static Guid GetGuid(this ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + return attrScope.Value.guid; + } + } + + public static Guid GetOrCreateGuid(this ITypeInfo typeInfo) + { + var guid = typeInfo.GetGuid(); + if (guid != Guid.Empty) + { + return guid; + } + + var guidBytes = typeInfo.GetContainingTypeLib().GetGuid().ToByteArray(); + + var nameBytes = BitConverter.GetBytes(typeInfo.GetName().GetDigestAsUInt64()); + for (var index = 0; index < guidBytes.Length; index++) + { + guidBytes[index] ^= nameBytes[index % nameBytes.Length]; + } + + return new Guid(guidBytes); + } + + public static TYPEFLAGS GetFlags(this ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + return attrScope.Value.wTypeFlags; + } + } + + public static TYPEKIND GetKind(this ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + return attrScope.Value.typekind; + } + } + + public static IEnumerable GetDispatchMembers(this ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + var count = attrScope.Value.cFuncs; + var isEnumerable = false; + + var names = new string[1]; + for (var index = 0; index < count; index++) + { + using (var funcDescScope = typeInfo.CreateFuncDescScope(index)) + { + if (funcDescScope.Value.memid == SpecialDispIDs.NewEnum) + { + isEnumerable = true; + } + + if ((funcDescScope.Value.wFuncFlags & (short)FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) + { + continue; + } + + typeInfo.GetNames(funcDescScope.Value.memid, names, 1, out var nameCount); + if (nameCount > 0) + { + yield return new DispatchMember(names[0], funcDescScope.Value.memid, funcDescScope.Value.invkind); + } + + if (isEnumerable) + { + yield return new DispatchMember("GetEnumerator", SpecialDispIDs.GetEnumerator, INVOKEKIND.INVOKE_FUNC); + } + } + } + } + } + + public static bool IsEnum(this ITypeInfo typeInfo) + { + using (var attrScope = typeInfo.CreateAttrScope()) + { + if (attrScope.Value.typekind == TYPEKIND.TKIND_ENUM) + { + return true; + } + + if (attrScope.Value.typekind == TYPEKIND.TKIND_ALIAS) + { + typeInfo.GetRefTypeInfo(unchecked((int)attrScope.Value.tdescAlias.lpValue.ToInt64()), out var refTypeInfo); + return refTypeInfo.IsEnum(); + } + + return false; + } + } + + public static IScope CreateAttrScope(this ITypeInfo typeInfo) + { + return StructHelpers.CreateScope(typeInfo.GetTypeAttr, typeInfo.ReleaseTypeAttr); + } + + public static IScope CreateVarDescScope(this ITypeInfo typeInfo, int index) + { + return StructHelpers.CreateScope((out IntPtr pVarDesc) => typeInfo.GetVarDesc(index, out pVarDesc), typeInfo.ReleaseVarDesc); + } + + public static IScope CreateFuncDescScope(this ITypeInfo typeInfo, int index) + { + return StructHelpers.CreateScope((out IntPtr pFuncDesc) => typeInfo.GetFuncDesc(index, out pFuncDesc), typeInfo.ReleaseFuncDesc); + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs.meta new file mode 100644 index 000000000..23383ff12 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeInfoHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 06f37c3ab41969d43bd165cb0a76592a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs b/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs new file mode 100644 index 000000000..81a81da51 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs @@ -0,0 +1,205 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using ELEMDESC = System.Runtime.InteropServices.ComTypes.ELEMDESC; +using FUNCDESC = System.Runtime.InteropServices.ComTypes.FUNCDESC; +using TYPEDESC = System.Runtime.InteropServices.ComTypes.TYPEDESC; +using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; +using VARDESC = System.Runtime.InteropServices.ComTypes.VARDESC; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class TypeLibHelpers + { + // GUID_ManagedName (um\cor.h) + private static readonly Guid managedNameGuid = new Guid("{0f21f359-ab84-41e8-9a78-36d110e6d2f9}"); + + public static string GetName(this ITypeLib typeLib) + { + return typeLib.GetMemberName(-1); + } + + public static string GetMemberName(this ITypeLib typeLib, int index) + { + typeLib.GetDocumentation(index, out var name, out _, out _, out _); + return name; + } + + public static string GetManagedName(this ITypeLib typeLib) + { + if (typeLib is ITypeLib2 typeLib2) + { + // ReSharper disable EmptyGeneralCatchClause + + try + { + var guid = managedNameGuid; + typeLib2.GetCustData(ref guid, out var data); + + if (data is string name) + { + name = name.Trim(); + if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) + { + return name.Substring(0, name.Length - 4); + } + + return name; + } + } + catch + { + } + + // ReSharper restore EmptyGeneralCatchClause + } + + return typeLib.GetName(); + } + + public static Guid GetGuid(this ITypeLib typeLib) + { + using (var attrScope = typeLib.CreateAttrScope()) + { + return attrScope.Value.guid; + } + } + + public static IScope CreateAttrScope(this ITypeLib typeLib) + { + return StructHelpers.CreateScope(typeLib.GetLibAttr, typeLib.ReleaseTLibAttr); + } + + public static IEnumerable GetReferencedEnums(this ITypeLib typeLib) + { + var processedTypeInfo = new Dictionary(); + + var count = typeLib.GetTypeInfoCount(); + for (var index = 0; index < count; index++) + { + typeLib.GetTypeInfo(index, out var typeInfo); + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, processedTypeInfo)) + { + yield return enumTypeInfo; + } + } + } + + private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, Dictionary processedTypeInfo) + { + if (typeInfo == null) + { + yield break; + } + + var guid = typeInfo.GetOrCreateGuid(); + + if (processedTypeInfo.ContainsKey(guid)) + { + yield break; + } + + processedTypeInfo.Add(guid, typeInfo); + + if (typeInfo.IsEnum()) + { + yield return typeInfo; + yield break; + } + + if (typeInfo.GetContainingTypeLib().GetGuid() != typeLib.GetGuid()) + { + yield break; + } + + using (var typeAttrScope = typeInfo.CreateAttrScope()) + { + for (var funcIndex = 0; funcIndex < typeAttrScope.Value.cFuncs; funcIndex++) + { + using (var funcDescScope = typeInfo.CreateFuncDescScope(funcIndex)) + { + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, funcDescScope.Value, processedTypeInfo)) + { + yield return enumTypeInfo; + } + } + } + + for (var varIndex = 0; varIndex < typeAttrScope.Value.cVars; varIndex++) + { + using (var varDescScope = typeInfo.CreateVarDescScope(varIndex)) + { + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, varDescScope.Value, processedTypeInfo)) + { + yield return enumTypeInfo; + } + } + } + + for (var implTypeIndex = 0; implTypeIndex < typeAttrScope.Value.cImplTypes; implTypeIndex++) + { + typeInfo.GetRefTypeOfImplType(implTypeIndex, out var href); + typeInfo.GetRefTypeInfo(href, out var refTypeInfo); + + var refGuid = refTypeInfo.GetGuid(); + if ((refGuid == typeof(IDispatch).GUID) || (refGuid == typeof(IDispatchEx).GUID)) + { + continue; + } + + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, refTypeInfo, processedTypeInfo)) + { + yield return enumTypeInfo; + } + } + } + } + + private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, FUNCDESC funcDesc, Dictionary processedTypeInfo) + { + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, funcDesc.elemdescFunc, processedTypeInfo)) + { + yield return enumTypeInfo; + } + + foreach (var elemDesc in StructHelpers.GetStructsFromArray(funcDesc.lprgelemdescParam, funcDesc.cParams)) + { + foreach (var enumTypeInfo in GetReferencedEnums(typeLib, typeInfo, elemDesc, processedTypeInfo)) + { + yield return enumTypeInfo; + } + } + } + + private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, VARDESC varDesc, Dictionary processedTypeInfo) + { + return GetReferencedEnums(typeLib, typeInfo, varDesc.elemdescVar, processedTypeInfo); + } + + private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, ELEMDESC elemDesc, Dictionary processedTypeInfo) + { + return GetReferencedEnums(typeLib, typeInfo, elemDesc.tdesc, processedTypeInfo); + } + + private static IEnumerable GetReferencedEnums(ITypeLib typeLib, ITypeInfo typeInfo, TYPEDESC typeDesc, Dictionary processedTypeInfo) + { + if ((typeDesc.vt == (short)VarEnum.VT_PTR) || (typeDesc.vt == (short)VarEnum.VT_CARRAY)) + { + return GetReferencedEnums(typeLib, typeInfo, (TYPEDESC)Marshal.PtrToStructure(typeDesc.lpValue, typeof(TYPEDESC)), processedTypeInfo); + } + + if (typeDesc.vt == (short)VarEnum.VT_USERDEFINED) + { + typeInfo.GetRefTypeInfo(unchecked((int)typeDesc.lpValue.ToInt64()), out var refTypeInfo); + return GetReferencedEnums(typeLib, refTypeInfo, processedTypeInfo); + } + + return Enumerable.Empty(); + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs.meta new file mode 100644 index 000000000..57c5d8464 --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/TypeLibHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b5d20feb2cdd0c4d88de2dfe1b1d041 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs b/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs new file mode 100644 index 000000000..b042b40bf --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util.COM +{ + internal static class UnknownHelpers + { + public static IntPtr QueryInterface(IntPtr pUnknown) + { + var iid = typeof(T).GUID; + HResult.Check(Marshal.QueryInterface(pUnknown, ref iid, out var pInterface)); + return pInterface; + } + + public static IntPtr QueryInterfaceNoThrow(IntPtr pUnknown) + { + var iid = typeof(T).GUID; + var result = Marshal.QueryInterface(pUnknown, ref iid, out var pInterface); + return (result == HResult.S_OK) ? pInterface : IntPtr.Zero; + } + + public static void ReleaseAndEmpty(ref IntPtr pInterface) + { + if (pInterface != IntPtr.Zero) + { + Marshal.Release(pInterface); + pInterface = IntPtr.Zero; + } + } + } +} diff --git a/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs.meta b/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs.meta new file mode 100644 index 000000000..f4c407e2e --- /dev/null +++ b/Unity/Package/Runtime/Util/COM/UnknownHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb7e8847ac3f0a949be2fb58aa8b3b78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/CoTaskMemBlock.cs b/Unity/Package/Runtime/Util/CoTaskMemBlock.cs new file mode 100644 index 000000000..5ab6800f4 --- /dev/null +++ b/Unity/Package/Runtime/Util/CoTaskMemBlock.cs @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript.Util +{ + internal class CoTaskMemBlock : IDisposable + { + public IntPtr Addr { get; private set; } + + public CoTaskMemBlock(int size) + { + Addr = Marshal.AllocCoTaskMem(size); + } + + protected virtual void Dispose(bool disposing) + { + if (Addr != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(Addr); + Addr = IntPtr.Zero; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~CoTaskMemBlock() + { + Dispose(false); + } + } + + internal sealed class CoTaskMemArrayBlock : CoTaskMemBlock + { + private readonly int elementSize; + private readonly int length; + + public CoTaskMemArrayBlock(int elementSize, int length) + : base(elementSize * length) + { + this.elementSize = elementSize; + this.length = length; + } + + public IntPtr GetAddr(int index) + { + if ((index < 0) || (index >= length)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + if (Addr == IntPtr.Zero) + { + throw new ObjectDisposedException(ToString()); + } + + return GetAddrInternal(index); + } + + private IntPtr GetAddrInternal(int index) + { + return Addr + (index * elementSize); + } + } + + internal sealed class CoTaskMemVariantBlock : CoTaskMemBlock + { + public CoTaskMemVariantBlock() + : base(DispatchHelpers.VariantSize) + { + NativeMethods.VariantInit(Addr); + } + + public CoTaskMemVariantBlock(object obj) + : base(DispatchHelpers.VariantSize) + { + Marshal.GetNativeVariantForObject(obj, Addr); + } + + #region CoTaskMemBlock overrides + + protected override void Dispose(bool disposing) + { + if (Addr != IntPtr.Zero) + { + NativeMethods.VariantClear(Addr); + } + + base.Dispose(disposing); + } + + #endregion + } + + internal sealed class CoTaskMemVariantArgsBlock : CoTaskMemBlock + { + private readonly int length; + + public CoTaskMemVariantArgsBlock(object[] args) + : base(args.Length * DispatchHelpers.VariantSize) + { + length = args.Length; + for (var index = 0; index < length; index++) + { + Marshal.GetNativeVariantForObject(args[index], GetAddrInternal(length - 1 - index)); + } + } + + public IntPtr GetAddr(int index) + { + if ((index < 0) || (index >= length)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + if (Addr == IntPtr.Zero) + { + throw new ObjectDisposedException(ToString()); + } + + return GetAddrInternal(length - 1 - index); + } + + private IntPtr GetAddrInternal(int index) + { + return Addr + (index * DispatchHelpers.VariantSize); + } + + #region CoTaskMemBlock overrides + + protected override void Dispose(bool disposing) + { + if (Addr != IntPtr.Zero) + { + for (var index = 0; index < length; index++) + { + NativeMethods.VariantClear(GetAddrInternal(index)); + } + } + + base.Dispose(disposing); + } + + #endregion + } + + internal sealed class CoTaskMemVariantArgsByRefBlock : CoTaskMemBlock + { + private readonly object[] args; + + public CoTaskMemVariantArgsByRefBlock(object[] args) + : base(args.Length * 2 * DispatchHelpers.VariantSize) + { + this.args = args; + for (var index = 0; index < args.Length; index++) + { + var pArg = GetAddrInternal(args.Length + index); + Marshal.GetNativeVariantForObject(args[index], pArg); + + var pArgRef = GetAddrInternal(args.Length - 1 - index); + NativeMethods.VariantInit(pArgRef); + Marshal.WriteInt16(pArgRef, 0, 0x400C /*VT_BYREF|VT_VARIANT*/); + Marshal.WriteIntPtr(pArgRef, sizeof(ushort) * 4, pArg); + } + } + + public IntPtr GetAddr(int index) + { + if ((index < 0) || (index >= args.Length)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + if (Addr == IntPtr.Zero) + { + throw new ObjectDisposedException(ToString()); + } + + return GetAddrInternal(args.Length - 1 - index); + } + + private IntPtr GetAddrInternal(int index) + { + return Addr + (index * DispatchHelpers.VariantSize); + } + + #region CoTaskMemBlock overrides + + protected override void Dispose(bool disposing) + { + if (Addr != IntPtr.Zero) + { + for (var index = 0; index < args.Length; index++) + { + var pArg = GetAddrInternal(args.Length + index); + args[index] = MiscHelpers.GetObjectForVariant(pArg); + NativeMethods.VariantClear(pArg); + } + } + + base.Dispose(disposing); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/CoTaskMemBlock.cs.meta b/Unity/Package/Runtime/Util/CoTaskMemBlock.cs.meta new file mode 100644 index 000000000..c0da4c95e --- /dev/null +++ b/Unity/Package/Runtime/Util/CoTaskMemBlock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd75a12b2ffaea547b496e505b294fa5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Collateral.cs b/Unity/Package/Runtime/Util/Collateral.cs new file mode 100644 index 000000000..08afae9e3 --- /dev/null +++ b/Unity/Package/Runtime/Util/Collateral.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Runtime.CompilerServices; + +namespace Microsoft.ClearScript.Util +{ + internal class CollateralObject + where THolder : class + where TValue : class + { + private readonly ConditionalWeakTable table = new ConditionalWeakTable(); + + public TValue Get(THolder holder) + { + return table.TryGetValue(holder, out var value) ? value : null; + } + + public TValue GetOrCreate(THolder holder) + { + return table.GetOrCreateValue(holder); + } + + public virtual void Set(THolder holder, TValue value) + { + Clear(holder); + if (value != null) + { + table.Add(holder, value); + } + } + + public void Clear(THolder holder) + { + table.Remove(holder); + } + } + + internal sealed class CollateralArray : CollateralObject where THolder : class + { + public override void Set(THolder holder, TElement[] value) + { + if (value == null) + { + Clear(holder); + } + else if (value.Length > 0) + { + base.Set(holder, value); + } + else + { + base.Set(holder, ArrayHelpers.GetEmptyArray()); + } + } + } +} diff --git a/Unity/Package/Runtime/Util/Collateral.cs.meta b/Unity/Package/Runtime/Util/Collateral.cs.meta new file mode 100644 index 000000000..7760bca96 --- /dev/null +++ b/Unity/Package/Runtime/Util/Collateral.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa9c0395faac63b4ebcc59aedbb7cc40 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs b/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs new file mode 100644 index 000000000..91d583260 --- /dev/null +++ b/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; + +namespace Microsoft.ClearScript.Util +{ + internal sealed class ConcurrentWeakSet where T : class + { + private readonly object dataLock = new object(); + private List weakRefs = new List(); + + public int Count => GetItems().Count; + + public bool Contains(T item) + { + MiscHelpers.VerifyNonNullArgument(item, nameof(item)); + return GetItems().Contains(item); + } + + public bool TryAdd(T item) + { + MiscHelpers.VerifyNonNullArgument(item, nameof(item)); + lock (dataLock) + { + if (!GetItemsInternal().Contains(item)) + { + weakRefs.Add(new WeakReference(item)); + return true; + } + + return false; + } + } + + public void ForEach(Action action) + { + MiscHelpers.VerifyNonNullArgument(action, nameof(action)); + GetItems().ForEach(action); + } + + private List GetItems() + { + lock (dataLock) + { + return GetItemsInternal(); + } + } + + private List GetItemsInternal() + { + var items = new List(); + var tempWeakRefs = new List(); + foreach (var weakRef in weakRefs) + { + if (weakRef.Target is T item) + { + items.Add(item); + tempWeakRefs.Add(weakRef); + } + } + + weakRefs = tempWeakRefs; + return items; + } + } +} diff --git a/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs.meta b/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs.meta new file mode 100644 index 000000000..0dc4dd094 --- /dev/null +++ b/Unity/Package/Runtime/Util/ConcurrentWeakSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c40b38f13433a9499414693b016da61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/DynamicHelpers.cs b/Unity/Package/Runtime/Util/DynamicHelpers.cs new file mode 100644 index 000000000..33c5e1bcf --- /dev/null +++ b/Unity/Package/Runtime/Util/DynamicHelpers.cs @@ -0,0 +1,889 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices.Expando; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript.Util +{ + internal static class DynamicHelpers + { + #region public members + + public static DynamicMetaObject Bind(DynamicMetaObjectBinder binder, object target, object[] args) + { + return binder.Bind(CreateDynamicTarget(target), CreateDynamicArgs(args)); + } + + public static object Invoke(Expression expr) + { + Debug.Assert(expr != null); + return Expression.Lambda(expr).Compile().DynamicInvoke(); + } + + public static object Invoke(Expression expr, IEnumerable parameters, object[] args) + { + Debug.Assert(expr != null); + return Expression.Lambda(expr, parameters).Compile().DynamicInvoke(args); + } + + public static bool TryBindAndInvoke(DynamicMetaObjectBinder binder, object target, object[] args, out object result) + { + try + { + // For COM member access, use IReflect/IExpando if possible. This works around + // some dynamic binder bugs and limitations observed during batch test runs. + + if ((target is IReflect reflect) && reflect.GetType().IsCOMObject) + { + if (binder is GetMemberBinder getMemberBinder) + { + if (TryGetProperty(reflect, getMemberBinder.Name, getMemberBinder.IgnoreCase, args, out result)) + { + return true; + } + } + else + { + if (binder is SetMemberBinder setMemberBinder) + { + if (TrySetProperty(reflect, setMemberBinder.Name, setMemberBinder.IgnoreCase, args, out result)) + { + return true; + } + } + else + { + if (binder is CreateInstanceBinder) + { + if (TryCreateInstance(reflect, args, out result)) + { + return true; + } + } + else + { + if (binder is InvokeBinder) + { + if (TryInvoke(reflect, args, out result)) + { + return true; + } + } + else + { + if (binder is InvokeMemberBinder invokeMemberBinder) + { + if (TryInvokeMethod(reflect, invokeMemberBinder.Name, invokeMemberBinder.IgnoreCase, args, out result)) + { + return true; + } + } + else if ((args != null) && (args.Length > 0)) + { + if (binder is GetIndexBinder) + { + if (TryGetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result)) + { + return true; + } + } + else + { + if (binder is SetIndexBinder) + { + if (TrySetProperty(reflect, args[0].ToString(), false, args.Skip(1).ToArray(), out result)) + { + return true; + } + } + } + } + } + } + } + } + } + + var binding = Bind(binder, target, args); + result = Invoke(binding.Expression); + return true; + } + catch (Exception exception) + { + result = exception; + return false; + } + } + + #endregion + + #region DynamicMetaObject extensions + + public static bool TryCreateInstance(this DynamicMetaObject target, object[] args, out object result) + { + return TryDynamicOperation(() => target.CreateInstance(args), out result); + } + + public static bool TryInvoke(this DynamicMetaObject target, IHostContext context, object[] args, out object result) + { + return TryDynamicOperation(() => target.Invoke(args), out result); + } + + public static bool TryInvokeMember(this DynamicMetaObject target, IHostContext context, string name, BindingFlags invokeFlags, object[] args, out object result) + { + return TryDynamicOperation(() => target.InvokeMember(context, name, invokeFlags, args), out result); + } + + public static bool TryGetMember(this DynamicMetaObject target, string name, out object result) + { + return TryDynamicOperation(() => target.GetMember(name), out result); + } + + public static bool TrySetMember(this DynamicMetaObject target, string name, object value, out object result) + { + return TryDynamicOperation(() => target.SetMember(name, value), out result); + } + + public static bool TryDeleteMember(this DynamicMetaObject target, string name, out bool result) + { + return TryDynamicOperation(() => target.DeleteMember(name), out result); + } + + public static bool TryGetIndex(this DynamicMetaObject target, object[] indices, out object result) + { + return TryDynamicOperation(() => target.GetIndex(indices), out result); + } + + public static bool TrySetIndex(this DynamicMetaObject target, object[] indices, object value, out object result) + { + return TryDynamicOperation(() => target.SetIndex(indices, value), out result); + } + + public static bool TryDeleteIndex(this DynamicMetaObject target, object[] indices, out bool result) + { + return TryDynamicOperation(() => target.DeleteIndex(indices), out result); + } + + public static bool TryConvert(this DynamicMetaObject target, Type type, bool @explicit, out object result) + { + return TryDynamicOperation(() => target.Convert(type, @explicit), out result); + } + + #endregion + + #region internal members + + private static bool TryGetProperty(IReflect target, string name, bool ignoreCase, object[] args, out object result) + { + // ReSharper disable once SuspiciousTypeConversion.Global + if (target is IDispatchEx dispatchEx) + { + // Standard IExpando-over-IDispatchEx support appears to leak the variants it + // creates for the invocation arguments. This issue has been reported. In the + // meantime we'll bypass this facility and interface with IDispatchEx directly. + + var value = dispatchEx.GetProperty(name, ignoreCase, args); + result = (value is Nonexistent) ? Undefined.Value : value; + return true; + } + + var flags = BindingFlags.Public; + if (ignoreCase) + { + flags |= BindingFlags.IgnoreCase; + } + + var property = target.GetProperty(name, flags); + if (property != null) + { + result = property.GetValue(target, args); + return true; + } + + result = null; + return false; + } + + private static bool TrySetProperty(IReflect target, string name, bool ignoreCase, object[] args, out object result) + { + if ((args != null) && (args.Length > 0)) + { + // ReSharper disable once SuspiciousTypeConversion.Global + if (target is IDispatchEx dispatchEx) + { + // Standard IExpando-over-IDispatchEx support appears to leak the variants it + // creates for the invocation arguments. This issue has been reported. In the + // meantime we'll bypass this facility and interface with IDispatchEx directly. + + dispatchEx.SetProperty(name, ignoreCase, args); + result = args[args.Length - 1]; + return true; + } + + var flags = BindingFlags.Public; + if (ignoreCase) + { + flags |= BindingFlags.IgnoreCase; + } + + var property = target.GetProperty(name, flags); + if (property == null) + { + if (target is IExpando expando) + { + property = expando.AddProperty(name); + } + } + + if (property != null) + { + property.SetValue(target, args[args.Length - 1], args.Take(args.Length - 1).ToArray()); + result = args[args.Length - 1]; + return true; + } + } + + result = null; + return false; + } + + private static bool TryCreateInstance(IReflect target, object[] args, out object result) + { + // ReSharper disable once SuspiciousTypeConversion.Global + if (target is IDispatchEx dispatchEx) + { + // Standard IExpando-over-IDispatchEx support appears to leak the variants it + // creates for the invocation arguments. This issue has been reported. In the + // meantime we'll bypass this facility and interface with IDispatchEx directly. + + result = dispatchEx.Invoke(true, args); + return true; + } + + try + { + result = target.InvokeMember(SpecialMemberNames.Default, BindingFlags.CreateInstance, null, target, args, null, CultureInfo.InvariantCulture, null); + return true; + } + catch (TargetInvocationException) + { + throw; + } + catch + { + result = null; + return false; + } + } + + private static bool TryInvoke(IReflect target, object[] args, out object result) + { + // ReSharper disable once SuspiciousTypeConversion.Global + if (target is IDispatchEx dispatchEx) + { + // Standard IExpando-over-IDispatchEx support appears to leak the variants it + // creates for the invocation arguments. This issue has been reported. In the + // meantime we'll bypass this facility and interface with IDispatchEx directly. + + result = dispatchEx.Invoke(false, args); + return true; + } + + try + { + result = target.InvokeMember(SpecialMemberNames.Default, BindingFlags.InvokeMethod, null, target, args, null, CultureInfo.InvariantCulture, null); + return true; + } + catch (TargetInvocationException) + { + throw; + } + catch + { + result = null; + return false; + } + } + + private static bool TryInvokeMethod(IReflect target, string name, bool ignoreCase, object[] args, out object result) + { + // ReSharper disable once SuspiciousTypeConversion.Global + if (target is IDispatchEx dispatchEx) + { + // Standard IExpando-over-IDispatchEx support appears to leak the variants it + // creates for the invocation arguments. This issue has been reported. In the + // meantime we'll bypass this facility and interface with IDispatchEx directly. + + result = dispatchEx.InvokeMethod(name, ignoreCase, args); + return true; + } + + var flags = BindingFlags.Public; + if (ignoreCase) + { + flags |= BindingFlags.IgnoreCase; + } + + var method = target.GetMethod(name, flags); + if (method != null) + { + result = method.Invoke(target, BindingFlags.InvokeMethod | flags, null, args, CultureInfo.InvariantCulture); + return true; + } + + result = null; + return false; + } + + private static bool TryDynamicOperation(Func operation, out T result) + { + try + { + result = operation(); + return true; + } + catch (TargetInvocationException exception) + { + if (exception.InnerException is InvalidDynamicOperationException) + { + result = default; + return false; + } + + throw; + } + } + + private static object CreateInstance(this DynamicMetaObject target, object[] args) + { + var paramNames = Enumerable.Range(0, args.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(args[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindCreateInstance(new DynamicCreateInstanceBinder(paramNames), parameters); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block, paramExprs, args); + } + + private static object Invoke(this DynamicMetaObject target, object[] args) + { + var paramNames = Enumerable.Range(0, args.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(args[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindInvoke(new DynamicInvokeBinder(paramNames), parameters); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block, paramExprs, args); + } + + private static object InvokeMember(this DynamicMetaObject target, IHostContext context, string name, BindingFlags invokeFlags, object[] args) + { + var paramNames = Enumerable.Range(0, args.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(args[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindInvokeMember(new DynamicInvokeMemberBinder(context, name, invokeFlags, paramNames), parameters); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block, paramExprs, args); + } + + private static object GetMember(this DynamicMetaObject target, string name) + { + var bindResult = target.BindGetMember(new DynamicGetMemberBinder(name)); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block); + } + + private static object SetMember(this DynamicMetaObject target, string name, object value) + { + var bindResult = target.BindSetMember(new DynamicSetMemberBinder(name), CreateDynamicArg(value)); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block); + } + + private static bool DeleteMember(this DynamicMetaObject target, string name) + { + var bindResult = target.BindDeleteMember(new DynamicDeleteMemberBinder(name)); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + + try + { + Invoke(block); + return true; + } + catch (TargetInvocationException exception) + { + if (exception.InnerException is InvalidDynamicOperationException) + { + return false; + } + + throw; + } + } + + private static object GetIndex(this DynamicMetaObject target, object[] indices) + { + var paramNames = Enumerable.Range(0, indices.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(indices[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindGetIndex(new DynamicGetIndexBinder(paramNames), parameters); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block, paramExprs, indices); + } + + private static object SetIndex(this DynamicMetaObject target, object[] indices, object value) + { + var paramNames = Enumerable.Range(0, indices.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(indices[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindSetIndex(new DynamicSetIndexBinder(paramNames), parameters, CreateDynamicArg(value)); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block, paramExprs, indices); + } + + private static bool DeleteIndex(this DynamicMetaObject target, object[] indices) + { + var paramNames = Enumerable.Range(0, indices.Length).Select(index => "a" + index).ToArray(); + var paramExprs = paramNames.Select((paramName, index) => Expression.Parameter(GetParamTypeForArg(indices[index]), paramName)).ToArray(); + var parameters = paramExprs.Select(paramExpr => new DynamicMetaObject(paramExpr, BindingRestrictions.Empty)).ToArray(); + var bindResult = target.BindDeleteIndex(new DynamicDeleteIndexBinder(paramNames), parameters); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + + try + { + Invoke(block, paramExprs, indices); + return true; + } + catch (TargetInvocationException exception) + { + if (exception.InnerException is InvalidDynamicOperationException) + { + return false; + } + + throw; + } + } + + private static object Convert(this DynamicMetaObject target, Type type, bool @explicit) + { + var bindResult = target.BindConvert(new DynamicConvertBinder(type, @explicit)); + var block = Expression.Block(Expression.Label(CallSiteBinder.UpdateLabel), bindResult.Expression); + return Invoke(block); + } + + private static DynamicMetaObject CreateDynamicTarget(object target) + { + if (target is IByRefArg byRefArg) + { + return CreateDynamicMetaObject(byRefArg.Value, Expression.Parameter(byRefArg.Type.MakeByRefType())); + } + + var hostTarget = target as HostTarget; + if (hostTarget == null) + { + return CreateDynamicMetaObject(target, Expression.Constant(target)); + } + + target = hostTarget.DynamicInvokeTarget; + if (hostTarget is HostType) + { + return CreateDynamicMetaObject(target, Expression.Constant(target)); + } + + var type = hostTarget.Type; + try + { + return CreateDynamicMetaObject(target, Expression.Constant(target, type)); + } + catch (ArgumentException) + { + return CreateDynamicMetaObject(target, Expression.Constant(target)); + } + } + + private static DynamicMetaObject CreateDynamicArg(object arg) + { + if (arg is IByRefArg byRefArg) + { + return CreateDynamicMetaObject(byRefArg.Value, Expression.Parameter(byRefArg.Type.MakeByRefType())); + } + + if (arg is HostType) + { + return CreateDynamicMetaObject(arg, Expression.Constant(arg)); + } + + var hostTarget = arg as HostTarget; + if (hostTarget == null) + { + return CreateDynamicMetaObject(arg, Expression.Constant(arg)); + } + + arg = hostTarget.Target; + + var type = hostTarget.Type; + try + { + return CreateDynamicMetaObject(arg, Expression.Constant(arg, type)); + } + catch (ArgumentException) + { + try + { + return CreateDynamicMetaObject(arg, Expression.Convert(Expression.Constant(arg), type)); + } + catch (InvalidOperationException) + { + return CreateDynamicMetaObject(arg, Expression.Constant(arg)); + } + } + } + + private static DynamicMetaObject[] CreateDynamicArgs(object[] args) + { + return args.Select(CreateDynamicArg).ToArray(); + } + + private static DynamicMetaObject CreateDynamicMetaObject(object value, Expression expr) + { + return new DynamicMetaObject(expr, BindingRestrictions.Empty, value); + } + + private static Expression CreateThrowExpr(string message) where T : Exception + { + var constructor = typeof(T).GetConstructor(new[] { typeof(string) }); + + Expression exceptionExpr; + if (constructor != null) + { + exceptionExpr = Expression.New(constructor, Expression.Constant(message)); + } + else + { + exceptionExpr = Expression.Constant(typeof(T).CreateInstance(message)); + } + + return Expression.Throw(exceptionExpr); + } + + private static Type GetParamTypeForArg(object arg) + { + return (arg != null) ? arg.GetType() : typeof(object); + } + + #endregion + + #region Nested type: DynamicCreateInstanceBinder + + private sealed class DynamicCreateInstanceBinder : CreateInstanceBinder + { + public DynamicCreateInstanceBinder(string[] paramNames) + : base(new CallInfo(paramNames.Length, paramNames)) + { + } + + public override DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic instantiation algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic instantiation. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic instantiation"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicInvokeBinder + + private sealed class DynamicInvokeBinder : InvokeBinder + { + public DynamicInvokeBinder(string[] paramNames) + : base(new CallInfo(paramNames.Length, paramNames)) + { + } + + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic invocation algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic invocation. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic object invocation"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicGetMemberBinder + + private sealed class DynamicGetMemberBinder : GetMemberBinder + { + public DynamicGetMemberBinder(string name) + : base(name, false) + { + } + + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic member retrieval algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic member retrieval. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic member retrieval"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicSetMemberBinder + + private sealed class DynamicSetMemberBinder : SetMemberBinder + { + public DynamicSetMemberBinder(string name) + : base(name, false) + { + } + + public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic member assignment algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic member assignment. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic member assignment"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicInvokeMemberBinder + + private sealed class DynamicInvokeMemberBinder : InvokeMemberBinder + { + private static readonly MethodInfo invokeMemberValueMethod = typeof(DynamicInvokeMemberBinder).GetMethod("InvokeMemberValue", BindingFlags.NonPublic | BindingFlags.Static); + private readonly IHostContext context; + private readonly BindingFlags invokeFlags; + + public DynamicInvokeMemberBinder(IHostContext context, string name, BindingFlags invokeFlags, string[] paramNames) + : base(name, false, new CallInfo(paramNames.Length, paramNames)) + { + this.context = context; + this.invokeFlags = invokeFlags; + } + + public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic member invocation algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic member invocation. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic member invocation"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // behave as in other scenarios, but the observed value is always null + return errorSuggestion; + } + + // construct an algorithm for invoking a member value + var argExprs = new[] { Expression.Constant(context), target.Expression, Expression.Constant(invokeFlags), Expression.NewArrayInit(typeof(object), args.Select(GetArgRefExpr)) }; + return new DynamicMetaObject(Expression.Call(invokeMemberValueMethod, argExprs), BindingRestrictions.Empty); + } + + private static Expression GetArgRefExpr(DynamicMetaObject arg) + { + var argExpr = arg.Expression; + return argExpr.Type.IsValueType ? Expression.Convert(argExpr, typeof(object)) : argExpr; + } + + // ReSharper disable UnusedMember.Local + + private static object InvokeMemberValue(IHostContext context, object target, BindingFlags invokeFlags, object[] args) + { + if (InvokeHelpers.TryInvokeObject(context, target, BindingFlags.InvokeMethod, args, args, true, out var result)) + { + return result; + } + + if (invokeFlags.HasFlag(BindingFlags.GetField) && (args.Length < 1)) + { + return target; + } + + throw new InvalidDynamicOperationException("Invalid dynamic member value invocation"); + } + + // ReSharper restore UnusedMember.Local + } + + #endregion + + #region Nested type: DynamicDeleteMemberBinder + + private sealed class DynamicDeleteMemberBinder : DeleteMemberBinder + { + public DynamicDeleteMemberBinder(string name) + : base(name, false) + { + } + + public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic member deletion algorithm + return errorSuggestion; + } + + // construct an algorithm for dealing with unsuccessful dynamic member deletion + return new DynamicMetaObject(CreateThrowExpr("Invalid dynamic member deletion"), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicGetIndexBinder + + private sealed class DynamicGetIndexBinder : GetIndexBinder + { + public DynamicGetIndexBinder(string[] paramNames) + : base(new CallInfo(paramNames.Length, paramNames)) + { + } + + public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic index retrieval algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic index retrieval. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic index retrieval"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicSetIndexBinder + + private sealed class DynamicSetIndexBinder : SetIndexBinder + { + public DynamicSetIndexBinder(string[] paramNames) + : base(new CallInfo(paramNames.Length, paramNames)) + { + } + + public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic index assignment algorithm + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic index assignment. + // A block returning a reference object appears to be required for some reason. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic index assignment"), Expression.Constant(Nonexistent.Value)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicDeleteIndexBinder + + private sealed class DynamicDeleteIndexBinder : DeleteIndexBinder + { + public DynamicDeleteIndexBinder(string[] paramNames) + : base(new CallInfo(paramNames.Length, paramNames)) + { + } + + public override DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indices, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + // errorSuggestion is the dynamic index deletion algorithm + return errorSuggestion; + } + + // construct an algorithm for dealing with unsuccessful dynamic index deletion + return new DynamicMetaObject(CreateThrowExpr("Invalid dynamic index deletion"), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: DynamicConvertBinder + + private sealed class DynamicConvertBinder : ConvertBinder + { + public DynamicConvertBinder(Type type, bool @explicit) + : base(type, @explicit) + { + } + + public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + { + if (errorSuggestion != null) + { + return errorSuggestion; + } + + // Construct an algorithm for dealing with unsuccessful dynamic conversion. + // The block must return an expression of the target type. + return new DynamicMetaObject(Expression.Block(CreateThrowExpr("Invalid dynamic conversion"), Expression.Default(Type)), BindingRestrictions.Empty); + } + } + + #endregion + + #region Nested type: InvalidDynamicOperationException + + [Serializable] + private sealed class InvalidDynamicOperationException : InvalidOperationException + { + public InvalidDynamicOperationException(string message) + : base(message) + { + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/DynamicHelpers.cs.meta b/Unity/Package/Runtime/Util/DynamicHelpers.cs.meta new file mode 100644 index 000000000..f57db67a9 --- /dev/null +++ b/Unity/Package/Runtime/Util/DynamicHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd268c3428f3c9e48be750b6902e98f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/EnumUtils.cs b/Unity/Package/Runtime/Util/EnumUtils.cs new file mode 100644 index 000000000..cfab726bf --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumUtils.cs @@ -0,0 +1,25 @@ +using System; + +internal static class EnumUtils +{ + public static unsafe bool HasFlagNonAlloc(this T x, T y) where T : unmanaged, Enum + { + switch (sizeof(T)) + { + case sizeof(byte): + return (*(byte*) &x & *(byte*) &y) != 0; + + case sizeof(short): + return (*(short*) &x & *(short*) &y) != 0; + + case sizeof(int): + return (*(int*) &x & *(int*) &y) != 0; + + case sizeof(long): + return (*(long*) &x & *(long*) &y) != 0L; + + default: + return false; + } + } +} \ No newline at end of file diff --git a/Unity/Package/Runtime/Util/EnumUtils.cs.meta b/Unity/Package/Runtime/Util/EnumUtils.cs.meta new file mode 100644 index 000000000..7bc35b00c --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74e99a080a0778047ae796c432833e2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs b/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs new file mode 100644 index 000000000..7299b1db9 --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs @@ -0,0 +1,188 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.ClearScript.JavaScript; + +namespace Microsoft.ClearScript.Util +{ + /// + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + public interface IScriptableAsyncEnumerator : IAsyncEnumerator + { + /// + T ScriptableCurrent { get; } + + /// + object ScriptableMoveNextAsync(); + + /// + object ScriptableDisposeAsync(); + } + + internal static partial class EnumerableHelpers + { + public static IScriptableAsyncEnumerator ToScriptableAsyncEnumerator(this IEnumerator enumerator, ScriptEngine engine) + { + return new ScriptableAsyncEnumeratorOnEnumerator(engine, enumerator); + } + + public static IScriptableAsyncEnumerator ToScriptableAsyncEnumerator(this IEnumerator enumerator, ScriptEngine engine) + { + return new ScriptableAsyncEnumeratorOnEnumerator(engine, enumerator); + } + + public static IScriptableAsyncEnumerator ToScriptableAsyncEnumerator(this IAsyncEnumerator enumerator, ScriptEngine engine) + { + return new ScriptableAsyncEnumeratorOnAsyncEnumerator(engine, enumerator); + } + } + + internal static partial class ScriptableEnumerableHelpers + { + public static object GetScriptableAsyncEnumerator(IEnumerable source, ScriptEngine engine) + { + return HostItem.Wrap(engine, source.GetEnumerator().ToScriptableAsyncEnumerator(engine), typeof(IScriptableAsyncEnumerator)); + } + } + + internal static partial class ScriptableEnumerableHelpers + { + public static object GetScriptableAsyncEnumerator(IEnumerable source, ScriptEngine engine) + { + return HostItem.Wrap(engine, source.GetEnumerator().ToScriptableAsyncEnumerator(engine), typeof(IScriptableAsyncEnumerator)); + } + + public static object GetScriptableAsyncEnumerator(IAsyncEnumerable source, ScriptEngine engine) + { + return HostItem.Wrap(engine, source.GetAsyncEnumerator().ToScriptableAsyncEnumerator(engine), typeof(IScriptableAsyncEnumerator)); + } + } + + internal abstract class ScriptableAsyncEnumerator : IScriptableAsyncEnumerator + { + private readonly ScriptEngine engine; + + protected ScriptableAsyncEnumerator(ScriptEngine engine) + { + this.engine = engine; + } + + #region IScriptableAsyncEnumerator implementation + + public T ScriptableCurrent => Current; + + public object ScriptableMoveNextAsync() + { + return MoveNextAsync().ToPromise(engine); + } + + public object ScriptableDisposeAsync() + { + return DisposeAsync().ToPromise(engine); + } + + #endregion + + #region IAsyncEnumerable implementation + + public abstract T Current { get; } + + public abstract ValueTask MoveNextAsync(); + + #endregion + + #region IAsyncDisposable implementation + + public abstract ValueTask DisposeAsync(); + + #endregion + } + + internal sealed class ScriptableAsyncEnumeratorOnEnumerator : ScriptableAsyncEnumerator + { + private readonly IEnumerator enumerator; + + public ScriptableAsyncEnumeratorOnEnumerator(ScriptEngine engine, IEnumerator enumerator) + : base(engine) + { + this.enumerator = enumerator; + } + + #region ScriptableAsyncEnumerator overrides + + public override object Current => enumerator.Current; + + public override ValueTask MoveNextAsync() + { + return new ValueTask(enumerator.MoveNext()); + } + + public override ValueTask DisposeAsync() + { + (enumerator as IDisposable)?.Dispose(); + return default; + } + + #endregion + } + + internal sealed class ScriptableAsyncEnumeratorOnEnumerator : ScriptableAsyncEnumerator + { + private readonly IEnumerator enumerator; + + public ScriptableAsyncEnumeratorOnEnumerator(ScriptEngine engine, IEnumerator enumerator) + : base(engine) + { + this.enumerator = enumerator; + } + + #region ScriptableAsyncEnumerator overrides + + public override T Current => enumerator.Current; + + public override ValueTask MoveNextAsync() + { + return new ValueTask(enumerator.MoveNext()); + } + + public override ValueTask DisposeAsync() + { + enumerator.Dispose(); + return default; + } + + #endregion + } + + internal sealed class ScriptableAsyncEnumeratorOnAsyncEnumerator : ScriptableAsyncEnumerator + { + private readonly IAsyncEnumerator enumerator; + + public ScriptableAsyncEnumeratorOnAsyncEnumerator(ScriptEngine engine, IAsyncEnumerator enumerator) + : base(engine) + { + this.enumerator = enumerator; + } + + #region ScriptableAsyncEnumerator overrides + + public override T Current => enumerator.Current; + + public override ValueTask MoveNextAsync() + { + return enumerator.MoveNextAsync(); + } + + public override ValueTask DisposeAsync() + { + return enumerator.DisposeAsync(); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs.meta b/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs.meta new file mode 100644 index 000000000..4ef357e3e --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumerableHelpers.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f190a82bf061def43bfe6f293539c8c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/EnumerableHelpers.cs b/Unity/Package/Runtime/Util/EnumerableHelpers.cs new file mode 100644 index 000000000..3d50ae12d --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumerableHelpers.cs @@ -0,0 +1,297 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript.Util +{ + /// + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + public interface IScriptableEnumerator : IEnumerator, IDisposable + { + /// + object ScriptableCurrent { get; } + + /// + bool ScriptableMoveNext(); + + /// + void ScriptableDispose(); + } + + /// + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + public interface IScriptableEnumerator : IScriptableEnumerator, IEnumerator + { + /// + new T ScriptableCurrent { get; } + } + + internal static partial class EnumerableHelpers + { + public static IList ToIList(this IEnumerable source) + { + return (source as IList) ?? source.ToList(); + } + + public static void ForEach(this IEnumerable source, Action action) + { + foreach (var element in source) + { + action(element); + } + } + + public static void ForEach(this IEnumerable source, Action action) + { + var index = 0; + foreach (var element in source) + { + action(element, index++); + } + } + + public static IEnumerable Flatten(this IEnumerable source, Func> selector) + { + foreach (var element in source) + { + yield return element; + + foreach (var descendant in selector(element).Flatten(selector)) + { + yield return descendant; + } + } + } + + public static IEnumerable ToEnumerable(this T element) + { + yield return element; + } + + public static IEnumerable ExcludeIndices(this IEnumerable names) + { + foreach (var name in names) + { + if (!int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out _)) + { + yield return name; + } + } + } + + public static IEnumerable GetIndices(this IEnumerable names) + { + foreach (var name in names) + { + if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + yield return index; + } + } + } + } + + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + internal static partial class ScriptableEnumerableHelpers + { + public static readonly HostType HostType = HostType.Wrap(typeof(ScriptableEnumerableHelpers)); + + public static object GetScriptableEnumerator(IEnumerable source) + { + return HostObject.Wrap(new ScriptableEnumeratorOnEnumerator(source.GetEnumerator()), typeof(IScriptableEnumerator)); + } + } + + [BypassCustomAttributeLoader] + [DefaultScriptUsage(ScriptAccess.Full)] + internal static partial class ScriptableEnumerableHelpers + { + public static readonly HostType HostType = HostType.Wrap(typeof(ScriptableEnumerableHelpers)); + + public static object GetScriptableEnumerator(IEnumerable source) + { + return HostObject.Wrap(new ScriptableEnumeratorOnEnumerator(source.GetEnumerator()), typeof(IScriptableEnumerator)); + } + } + + internal sealed class ScriptableEnumeratorOnEnumerator : IScriptableEnumerator + { + private readonly IEnumerator enumerator; + + public ScriptableEnumeratorOnEnumerator(IEnumerator enumerator) + { + this.enumerator = enumerator; + } + + #region IScriptableEnumerator implementation + + public object ScriptableCurrent => Current; + + public bool ScriptableMoveNext() + { + return MoveNext(); + } + + public void ScriptableDispose() + { + Dispose(); + } + + #endregion + + #region IEnumerator implementation + + public object Current => enumerator.Current; + + public bool MoveNext() + { + return enumerator.MoveNext(); + } + + public void Reset() + { + enumerator.Reset(); + } + + #endregion + + #region IDisposable implementation + + public void Dispose() + { + (enumerator as IDisposable)?.Dispose(); + } + + #endregion + } + + internal sealed class ScriptableEnumeratorOnEnumerator : IScriptableEnumerator + { + private readonly IEnumerator enumerator; + + public ScriptableEnumeratorOnEnumerator(IEnumerator enumerator) + { + this.enumerator = enumerator; + } + + #region IScriptableEnumerator implementation + + public T ScriptableCurrent => Current; + + #endregion + + #region IScriptableEnumerator implementation + + object IScriptableEnumerator.ScriptableCurrent => ScriptableCurrent; + + public bool ScriptableMoveNext() + { + return MoveNext(); + } + + public void ScriptableDispose() + { + Dispose(); + } + + #endregion + + #region IEnumerator implementation + + public T Current => enumerator.Current; + + #endregion + + #region IEnumerator implementation + + object IEnumerator.Current => Current; + + public bool MoveNext() + { + return enumerator.MoveNext(); + } + + public void Reset() + { + enumerator.Reset(); + } + + #endregion + + #region IDisposable implementation + + public void Dispose() + { + enumerator.Dispose(); + } + + #endregion + } + + internal sealed class ScriptableEnumeratorOnEnumVariant : IScriptableEnumerator + { + private readonly IEnumVARIANT enumVariant; + + public ScriptableEnumeratorOnEnumVariant(IEnumVARIANT enumVariant) + { + this.enumVariant = enumVariant; + } + + #region IScriptableEnumerator implementation + + public object ScriptableCurrent => Current; + + public bool ScriptableMoveNext() + { + return MoveNext(); + } + + public void ScriptableDispose() + { + Dispose(); + } + + #endregion + + #region IEnumerator implementation + + public object Current { get; private set; } + + public bool MoveNext() + { + var items = new object[1]; + if (enumVariant.Next(1, items, IntPtr.Zero) == HResult.S_OK) + { + Current = items[0]; + return true; + } + + return false; + } + + public void Reset() + { + enumVariant.Reset(); + } + + #endregion + + #region IDisposable implementation + + public void Dispose() + { + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/EnumerableHelpers.cs.meta b/Unity/Package/Runtime/Util/EnumerableHelpers.cs.meta new file mode 100644 index 000000000..3855c674f --- /dev/null +++ b/Unity/Package/Runtime/Util/EnumerableHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b511a65214cd584f9ab7432e07e2d6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Holder.cs b/Unity/Package/Runtime/Util/Holder.cs new file mode 100644 index 000000000..0f52d0d2e --- /dev/null +++ b/Unity/Package/Runtime/Util/Holder.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal interface IHolder + { + object Value { get; set; } + } + + internal class Holder : IHolder + { + public T Value { get; set; } + + #region IHolder implementation + + object IHolder.Value + { + get => Value; + set => Value = (T)value; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/Holder.cs.meta b/Unity/Package/Runtime/Util/Holder.cs.meta new file mode 100644 index 000000000..d68ce930b --- /dev/null +++ b/Unity/Package/Runtime/Util/Holder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4510c2ebf17f484a9fd3e8e964d98b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/IDynamic.cs b/Unity/Package/Runtime/Util/IDynamic.cs new file mode 100644 index 000000000..194d990cc --- /dev/null +++ b/Unity/Package/Runtime/Util/IDynamic.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal interface IDynamic + { + object GetProperty(string name, params object[] args); + object GetProperty(string name, out bool isCacheable, params object[] args); + void SetProperty(string name, params object[] args); + bool DeleteProperty(string name); + string[] GetPropertyNames(); + + object GetProperty(int index); + void SetProperty(int index, object value); + bool DeleteProperty(int index); + int[] GetPropertyIndices(); + + object Invoke(bool asConstructor, params object[] args); + object InvokeMethod(string name, params object[] args); + } +} diff --git a/Unity/Package/Runtime/Util/IDynamic.cs.meta b/Unity/Package/Runtime/Util/IDynamic.cs.meta new file mode 100644 index 000000000..d7eb98173 --- /dev/null +++ b/Unity/Package/Runtime/Util/IDynamic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa1951e984d35e343bd73dfee8f851d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/IExpando.cs b/Unity/Package/Runtime/Util/IExpando.cs new file mode 100644 index 000000000..3d5900105 --- /dev/null +++ b/Unity/Package/Runtime/Util/IExpando.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Reflection; + +namespace System.Runtime.InteropServices.Expando +{ + internal interface IExpando : IReflect + { + FieldInfo AddField(string name); + PropertyInfo AddProperty(string name); + MethodInfo AddMethod(string name, Delegate method); + void RemoveMember(MemberInfo member); + } +} diff --git a/Unity/Package/Runtime/Util/IExpando.cs.meta b/Unity/Package/Runtime/Util/IExpando.cs.meta new file mode 100644 index 000000000..0678bcd9b --- /dev/null +++ b/Unity/Package/Runtime/Util/IExpando.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67e2eb428af26cd4398a7ebdfb76e7b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/IHostContext.cs b/Unity/Package/Runtime/Util/IHostContext.cs new file mode 100644 index 000000000..2eb98310b --- /dev/null +++ b/Unity/Package/Runtime/Util/IHostContext.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.Util +{ + internal interface IHostContext + { + CustomAttributeLoader CustomAttributeLoader { get; } + ScriptEngine Engine { get; } + Type AccessContext { get; } + ScriptAccess DefaultAccess { get; } + } +} diff --git a/Unity/Package/Runtime/Util/IHostContext.cs.meta b/Unity/Package/Runtime/Util/IHostContext.cs.meta new file mode 100644 index 000000000..b5b6241f6 --- /dev/null +++ b/Unity/Package/Runtime/Util/IHostContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f3c3802023d578409e00ebc3c43085c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/IHostTargetContext.cs b/Unity/Package/Runtime/Util/IHostTargetContext.cs new file mode 100644 index 000000000..db6a49c9d --- /dev/null +++ b/Unity/Package/Runtime/Util/IHostTargetContext.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal interface IHostTargetContext : IHostContext + { + HostTargetFlags TargetFlags { get; } + } +} diff --git a/Unity/Package/Runtime/Util/IHostTargetContext.cs.meta b/Unity/Package/Runtime/Util/IHostTargetContext.cs.meta new file mode 100644 index 000000000..b89beab11 --- /dev/null +++ b/Unity/Package/Runtime/Util/IHostTargetContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c4f040ca03415142a3b70f46d4e6a94 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/INativeCallback.cs b/Unity/Package/Runtime/Util/INativeCallback.cs new file mode 100644 index 000000000..6d37638fc --- /dev/null +++ b/Unity/Package/Runtime/Util/INativeCallback.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.Util +{ + internal interface INativeCallback : IDisposable + { + void Invoke(); + } +} diff --git a/Unity/Package/Runtime/Util/INativeCallback.cs.meta b/Unity/Package/Runtime/Util/INativeCallback.cs.meta new file mode 100644 index 000000000..6190d218a --- /dev/null +++ b/Unity/Package/Runtime/Util/INativeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea72bd4f401a34c4383b914d21b09860 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs b/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs new file mode 100644 index 000000000..48b4bb9f6 --- /dev/null +++ b/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal interface IScriptMarshalWrapper + { + ScriptEngine Engine { get; } + object Unwrap(); + } +} diff --git a/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs.meta b/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs.meta new file mode 100644 index 000000000..997976f12 --- /dev/null +++ b/Unity/Package/Runtime/Util/IScriptMarshalWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46124f4b172a12f4d8732bddc63579d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/InvokeHelpers.cs b/Unity/Package/Runtime/Util/InvokeHelpers.cs new file mode 100644 index 000000000..1fc1bacfc --- /dev/null +++ b/Unity/Package/Runtime/Util/InvokeHelpers.cs @@ -0,0 +1,218 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq.Expressions; +using System.Reflection; + +namespace Microsoft.ClearScript.Util +{ + internal static class InvokeHelpers + { + public static object InvokeMethod(IHostContext context, MethodInfo method, object target, object[] args, ScriptMemberFlags flags) + { + return InvokeMethodInternal(context, method, target, args, (invokeMethod, invokeTarget, invokeArgs) => invokeMethod.Invoke(invokeTarget, invokeArgs), method.ReturnType, flags); + } + + public static object InvokeConstructor(IHostContext context, ConstructorInfo constructor, object[] args) + { + return InvokeMethodInternal(context, constructor, null, args, (invokeConstructor, invokeTarget, invokeArgs) => invokeConstructor.Invoke(invokeArgs), constructor.DeclaringType, ScriptMemberFlags.None); + } + + public static object InvokeDelegate(IHostContext context, Delegate del, object[] args) + { + return InvokeMethod(context, del.GetType().GetMethod("Invoke"), del, args, ScriptMemberFlags.None); + } + + public static bool TryInvokeObject(IHostContext context, object target, BindingFlags invokeFlags, object[] args, object[] bindArgs, bool tryDynamic, out object result) + { + if (target is HostTarget hostTarget) + { + if (hostTarget.TryInvoke(context, invokeFlags, args, bindArgs, out result)) + { + return true; + } + + if (hostTarget is HostType) + { + return false; + } + + target = hostTarget.InvokeTarget; + tryDynamic = tryDynamic && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(hostTarget.Type); + } + + if ((target != null) && invokeFlags.HasFlag(BindingFlags.InvokeMethod)) + { + if (target is ScriptItem scriptItem) + { + target = DelegateFactory.CreateFunc(scriptItem.Engine, target, args.Length); + } + + if (target is Delegate del) + { + result = InvokeDelegate(context, del, args); + return true; + } + + if (tryDynamic) + { + if (target is IDynamicMetaObjectProvider dynamicMetaObjectProvider) + { + if (dynamicMetaObjectProvider.GetMetaObject(Expression.Constant(target)).TryInvoke(context, args, out result)) + { + return true; + } + } + } + } + + result = null; + return false; + } + + private static object InvokeMethodInternal(IHostContext context, T method, object target, object[] args, Func invoker, Type returnType, ScriptMemberFlags flags) where T : MethodBase + { + var argList = new List(); + var byRefArgInfo = new List(); + object tailArgsArg = null; + + var parameters = method.GetParameters(); + for (var index = 0; index < parameters.Length; index++) + { + var param = parameters[index]; + if (CustomAttributes.Has(context, param, false)) + { + if ((index != (args.Length - 1)) || !param.ParameterType.IsInstanceOfType(args[index])) + { + var tailArgType = param.ParameterType.GetElementType(); + var tailArgs = Array.CreateInstance(tailArgType, Math.Max(args.Length - index, 0)); + for (var innerIndex = index; innerIndex < args.Length; innerIndex++) + { + var byRefArg = args[innerIndex] as IByRefArg; + if (byRefArg == null) + { + tailArgs.SetValue(GetCompatibleArg(param.Name, tailArgType, args[innerIndex]), innerIndex - index); + } + else + { + tailArgs.SetValue(GetCompatibleArg(param.Name, tailArgType, byRefArg.Value), innerIndex - index); + byRefArgInfo.Add(new ByRefArgItem(byRefArg, tailArgs, innerIndex - index)); + } + } + + argList.Add(tailArgs); + tailArgsArg = tailArgs; + break; + } + } + + if ((index < args.Length) && !(args[index] is Missing)) + { + var byRefArg = args[index] as IByRefArg; + if (byRefArg == null) + { + argList.Add(GetCompatibleArg(param, args[index])); + } + else + { + argList.Add(GetCompatibleArg(param, byRefArg.Value)); + byRefArgInfo.Add(new ByRefArgItem(byRefArg, null, index)); + } + } + else if (param.IsOptional) + { + if (param.Attributes.HasFlag(ParameterAttributes.HasDefault)) + { + try + { + argList.Add(param.DefaultValue); + } + catch (FormatException) + { + // undocumented but observed when calling HostFunctions.newVar() + argList.Add(null); + } + } + else + { + argList.Add(Missing.Value); + } + } + else + { + break; + } + } + + var finalArgs = argList.ToArray(); + var result = invoker(method, target, finalArgs); + + foreach (var item in byRefArgInfo) + { + var array = item.Array ?? finalArgs; + item.ByRefArg.Value = array.GetValue(item.Index); + } + + for (var index = 0; index < finalArgs.Length; index++) + { + if (index >= args.Length) + { + break; + } + + var finalArg = finalArgs[index]; + if (ReferenceEquals(finalArg, tailArgsArg)) + { + break; + } + + args[index] = finalArg; + } + + if (returnType == typeof(void)) + { + return context.Engine.VoidResultValue; + } + + return context.Engine.PrepareResult(result, returnType, flags, false); + } + + private static object GetCompatibleArg(ParameterInfo param, object value) + { + return GetCompatibleArg(param.Name, param.ParameterType, value); + } + + private static object GetCompatibleArg(string paramName, Type type, object value) + { + if (!type.IsAssignableFromValue(ref value)) + { + throw new ArgumentException(MiscHelpers.FormatInvariant("Invalid argument specified for parameter '{0}'", paramName)); + } + + return value; + } + + #region Nested type: ByRefArgItem + + private sealed class ByRefArgItem + { + public IByRefArg ByRefArg { get; } + + public Array Array { get; } + + public int Index { get; } + + public ByRefArgItem(IByRefArg arg, Array array, int index) + { + ByRefArg = arg; + Array = array; + Index = index; + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/InvokeHelpers.cs.meta b/Unity/Package/Runtime/Util/InvokeHelpers.cs.meta new file mode 100644 index 000000000..90bc32815 --- /dev/null +++ b/Unity/Package/Runtime/Util/InvokeHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 022f5edb022ea4b43b10892a7d96edbe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/MemberComparer.cs b/Unity/Package/Runtime/Util/MemberComparer.cs new file mode 100644 index 000000000..46bd0c9e2 --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberComparer.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; +using System.Reflection; + +namespace Microsoft.ClearScript.Util +{ + internal sealed class MemberComparer : EqualityComparer where T : MemberInfo + { + public static readonly MemberComparer Instance = new MemberComparer(); + + private MemberComparer() + { + } + + public override bool Equals(T x, T y) + { + if (ReferenceEquals(x, y)) + { + return true; + } + + if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) + { + return false; + } + + return MiscHelpers.Try(out var result, () => UnsafeEquals(x, y)) && result; + } + + public override int GetHashCode(T obj) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + return ReferenceEquals(obj, null) ? 0 : obj.GetHashCode(); + } + + private static bool UnsafeEquals(T x, T y) + { + return (x.Module == y.Module) && (x.MetadataToken == y.MetadataToken); + } + } +} diff --git a/Unity/Package/Runtime/Util/MemberComparer.cs.meta b/Unity/Package/Runtime/Util/MemberComparer.cs.meta new file mode 100644 index 000000000..e018c8d17 --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c869d47f01d814e458001cdc22d145b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/MemberHelpers.cs b/Unity/Package/Runtime/Util/MemberHelpers.cs new file mode 100644 index 000000000..15b18f8c7 --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberHelpers.cs @@ -0,0 +1,350 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util +{ + internal static class MemberHelpers + { + public static bool IsScriptable(this EventInfo eventInfo, IHostContext context) + { + return !eventInfo.IsSpecialName && !eventInfo.IsExplicitImplementation() && eventInfo.IsAccessible(context) && !eventInfo.IsBlockedFromScript(context, context.DefaultAccess); + } + + public static bool IsScriptable(this FieldInfo field, IHostContext context) + { + return !field.IsSpecialName && field.IsAccessible(context) && !field.IsBlockedFromScript(context, context.DefaultAccess); + } + + public static bool IsScriptable(this MethodInfo method, IHostContext context) + { + return !method.IsSpecialName && !method.IsExplicitImplementation() && method.IsAccessible(context) && !method.IsBlockedFromScript(context, context.DefaultAccess); + } + + public static bool IsScriptable(this PropertyInfo property, IHostContext context) + { + return !property.IsSpecialName && !property.IsExplicitImplementation() && property.IsAccessible(context) && !property.IsBlockedFromScript(context, context.DefaultAccess); + } + + public static bool IsScriptable(this Type type, IHostContext context) + { + return !type.IsSpecialName && type.IsAccessible(context) && !type.IsBlockedFromScript(context, context.DefaultAccess); + } + + public static bool IsAccessible(this EventInfo eventInfo, IHostContext context) + { + return eventInfo.AddMethod.IsAccessible(context); + } + + public static bool IsAccessible(this FieldInfo field, IHostContext context) + { + var type = field.DeclaringType; + + if (!type.IsAccessible(context)) + { + return false; + } + + var access = field.Attributes & FieldAttributes.FieldAccessMask; + + if (access == FieldAttributes.Public) + { + return true; + } + + var accessContext = context.AccessContext; + + if (accessContext == null) + { + return false; + } + + if (access == FieldAttributes.Private) + { + return type.EqualsOrDeclares(accessContext); + } + + if (access == FieldAttributes.Family) + { + return accessContext.IsFamilyOf(type); + } + + if (access == FieldAttributes.Assembly) + { + return accessContext.IsFriendOf(context, type); + } + + if (access == FieldAttributes.FamORAssem) + { + return accessContext.IsFamilyOf(type) || accessContext.IsFriendOf(context, type); + } + + if (access == FieldAttributes.FamANDAssem) + { + return accessContext.IsFamilyOf(type) && accessContext.IsFriendOf(context, type); + } + + return false; + } + + public static bool IsAccessible(this MethodBase method, IHostContext context) + { + var type = method.DeclaringType; + + if (!type.IsAccessible(context)) + { + return false; + } + + var access = method.Attributes & MethodAttributes.MemberAccessMask; + + if (access == MethodAttributes.Public) + { + return true; + } + + var accessContext = context.AccessContext; + + if (accessContext == null) + { + return false; + } + + if (access == MethodAttributes.Private) + { + return type.EqualsOrDeclares(accessContext); + } + + if (access == MethodAttributes.Family) + { + return accessContext.IsFamilyOf(type); + } + + if (access == MethodAttributes.Assembly) + { + return accessContext.IsFriendOf(context, type); + } + + if (access == MethodAttributes.FamORAssem) + { + return accessContext.IsFamilyOf(type) || accessContext.IsFriendOf(context, type); + } + + if (access == MethodAttributes.FamANDAssem) + { + return accessContext.IsFamilyOf(type) && accessContext.IsFriendOf(context, type); + } + + return false; + } + + public static bool IsAccessible(this MethodInfo method, IHostContext context) + { + return ((MethodBase)method.GetBaseDefinition()).IsAccessible(context); + } + + public static bool IsAccessible(this PropertyInfo property, IHostContext context) + { + var getMethod = property.GetMethod; + if ((getMethod != null) && getMethod.IsAccessible(context)) + { + return true; + } + + var setMethod = property.SetMethod; + if ((setMethod != null) && setMethod.IsAccessible(context)) + { + return true; + } + + return false; + } + + public static bool IsAccessible(this Type type, IHostContext context) + { + var visibility = (type.IsAnonymous(context) && !context.Engine.EnforceAnonymousTypeAccess) ? TypeAttributes.Public : type.Attributes & TypeAttributes.VisibilityMask; + + if (visibility == TypeAttributes.Public) + { + return true; + } + + var accessContext = context.AccessContext; + + if (accessContext == null) + { + return (visibility == TypeAttributes.NestedPublic) && type.DeclaringType.IsAccessible(context); + } + + if (visibility == TypeAttributes.NotPublic) + { + return accessContext.IsFriendOf(context, type); + } + + type = type.DeclaringType; + + if (!type.IsAccessible(context)) + { + return false; + } + + if (visibility == TypeAttributes.NestedPublic) + { + return true; + } + + if (visibility == TypeAttributes.NestedPrivate) + { + return type.EqualsOrDeclares(accessContext); + } + + if (visibility == TypeAttributes.NestedFamily) + { + return accessContext.IsFamilyOf(type); + } + + if (visibility == TypeAttributes.NestedAssembly) + { + return accessContext.IsFriendOf(context, type); + } + + if (visibility == TypeAttributes.NestedFamORAssem) + { + return accessContext.IsFamilyOf(type) || accessContext.IsFriendOf(context, type); + } + + if (visibility == TypeAttributes.NestedFamANDAssem) + { + return accessContext.IsFamilyOf(type) && accessContext.IsFriendOf(context, type); + } + + return false; + } + + public static string GetScriptName(this MemberInfo member, IHostContext context) + { + var attribute = member.GetOrLoadCustomAttribute(context); + return attribute?.Name ?? member.GetShortName(); + } + + public static bool IsBlockedFromScript(this MemberInfo member, IHostContext context, ScriptAccess defaultAccess, bool chain = true) + { + return member.GetScriptAccess(context, defaultAccess, chain) == ScriptAccess.None; + } + + public static bool IsReadOnlyForScript(this MemberInfo member, IHostContext context, ScriptAccess defaultAccess) + { + return member.GetScriptAccess(context, defaultAccess) == ScriptAccess.ReadOnly; + } + + public static ScriptAccess GetScriptAccess(this MemberInfo member, IHostContext context, ScriptAccess defaultValue, bool chain = true) + { + var attribute = member.GetOrLoadCustomAttribute(context); + if (attribute != null) + { + return attribute.Access; + } + + if (chain) + { + var declaringType = member.DeclaringType; + if (declaringType != null) + { + var testType = declaringType; + do + { + if (testType.IsNested) + { + var nestedTypeAttribute = testType.GetOrLoadCustomAttribute(context); + if (nestedTypeAttribute != null) + { + return nestedTypeAttribute.Access; + } + } + + var typeAttribute = testType.GetOrLoadCustomAttribute(context); + if (typeAttribute != null) + { + return typeAttribute.Access; + } + + testType = testType.DeclaringType; + + } while (testType != null); + + var assemblyAttribute = declaringType.Assembly.GetOrLoadCustomAttribute(context); + if (assemblyAttribute != null) + { + return assemblyAttribute.Access; + } + } + } + + return defaultValue; + } + + public static bool IsRestrictedForScript(this MemberInfo member, IHostContext context) + { + return !member.GetScriptMemberFlags(context).HasFlag(ScriptMemberFlags.ExposeRuntimeType); + } + + public static bool IsDispID(this MemberInfo member, IHostContext context, int dispid) + { + var attribute = member.GetOrLoadCustomAttribute(context); + return (attribute != null) && (attribute.Value == dispid); + } + + public static ScriptMemberFlags GetScriptMemberFlags(this MemberInfo member, IHostContext context) + { + var attribute = member.GetOrLoadCustomAttribute(context); + return attribute?.Flags ?? ScriptMemberFlags.None; + } + + public static string GetShortName(this MemberInfo member) + { + var name = member.Name; + var index = name.LastIndexOf('.'); + return (index >= 0) ? name.Substring(index + 1) : name; + } + + public static T GetOrLoadCustomAttribute(this MemberInfo member, IHostContext context, bool inherit = true) where T : Attribute + { + try + { + return CustomAttributes.GetOrLoad(context, member, inherit).SingleOrDefault(); + } + catch (AmbiguousMatchException) + { + if (inherit) + { + // this affects SqlDataReader and is indicative of a .NET issue described here: + // http://connect.microsoft.com/VisualStudio/feedback/details/646399/attribute-isdefined-throws-ambiguousmatchexception-for-indexer-properties-and-inherited-attributes + + return CustomAttributes.GetOrLoad(context, member, false).SingleOrDefault(); + } + + throw; + } + } + + public static IEnumerable GetOrLoadCustomAttributes(this MemberInfo member, IHostContext context, bool inherit = true) where T : Attribute + { + return CustomAttributes.GetOrLoad(context, member, inherit); + } + + public static bool HasCustomAttributes(this MemberInfo member, IHostContext context, bool inherit = true) where T : Attribute + { + return CustomAttributes.Has(context, member, inherit); + } + + private static bool IsExplicitImplementation(this MemberInfo member) + { + return member.Name.IndexOf('.') >= 0; + } + } +} diff --git a/Unity/Package/Runtime/Util/MemberHelpers.cs.meta b/Unity/Package/Runtime/Util/MemberHelpers.cs.meta new file mode 100644 index 000000000..da49458f5 --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 296e31f428627384eacb1174de915aaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/MemberMap.cs b/Unity/Package/Runtime/Util/MemberMap.cs new file mode 100644 index 000000000..6cc883533 --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberMap.cs @@ -0,0 +1,357 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; + +namespace Microsoft.ClearScript.Util +{ + internal static class MemberMap + { + private static readonly MemberMapImpl fieldMap = new MemberMapImpl(); + private static readonly MemberMapImpl methodMap = new MemberMapImpl(); + private static readonly MemberMapImpl propertyMap = new MemberMapImpl(); + + public static FieldInfo GetField(string name) + { + return fieldMap.GetMember(name); + } + + public static FieldInfo[] GetFields(string[] names) + { + // ReSharper disable once CoVariantArrayConversion + return fieldMap.GetMembers(names); + } + + public static MethodInfo GetMethod(string name) + { + return methodMap.GetMember(name); + } + + public static MethodInfo[] GetMethods(string[] names) + { + // ReSharper disable once CoVariantArrayConversion + return methodMap.GetMembers(names); + } + + public static PropertyInfo GetProperty(string name) + { + return propertyMap.GetMember(name); + } + + public static PropertyInfo[] GetProperties(string[] names) + { + // ReSharper disable once CoVariantArrayConversion + return propertyMap.GetMembers(names); + } + + // ReSharper disable ClassNeverInstantiated.Local + + #region Nested type: Field + + private sealed class Field : FieldInfo + { + public Field(string name) + { + Name = name; + } + + #region FieldInfo overrides + + public override FieldAttributes Attributes => FieldAttributes.Public; + // This occurs during VB-based dynamic script item invocation. It was not + // observed before script items gained an IReflect/IExpando implementation that + // exposes script item properties as fields. Apparently VB's dynamic invocation + // support not only recognizes IReflect/IExpando but actually favors it over + // DynamicObject. + + public override RuntimeFieldHandle FieldHandle => throw new NotImplementedException(); + + public override Type FieldType => typeof(object); + // This occurs during VB-based dynamic script item invocation. It was not + // observed before script items gained an IReflect/IExpando implementation that + // exposes script item properties as fields. Apparently VB's dynamic invocation + // support not only recognizes IReflect/IExpando but actually favors it over + // DynamicObject. + + public override Type DeclaringType => typeof(object); + // This occurs during VB-based dynamic script item invocation. It was not + // observed before script items gained an IReflect/IExpando implementation that + // exposes script item properties as fields. Apparently VB's dynamic invocation + // support not only recognizes IReflect/IExpando but actually favors it over + // DynamicObject. + + public override string Name { get; } + + public override Type ReflectedType => throw new NotImplementedException(); + + public override object GetValue(object obj) + { + // This occurs during VB-based dynamic script item invocation. It was not observed + // before script items gained an IReflect/IExpando implementation that exposes + // script item properties as fields. Apparently VB's dynamic invocation support not + // only recognizes IReflect/IExpando but actually favors it over DynamicObject. + + if (obj is IReflect reflect) + { + return reflect.InvokeMember(Name, BindingFlags.GetField, null, obj, ArrayHelpers.GetEmptyArray(), null, CultureInfo.InvariantCulture, null); + } + + throw new InvalidOperationException("Invalid field retrieval"); + } + + public override void SetValue(object obj, object value, BindingFlags invokeFlags, Binder binder, CultureInfo culture) + { + // This occurs during VB-based dynamic script item invocation. It was not observed + // before script items gained an IReflect/IExpando implementation that exposes + // script item properties as fields. Apparently VB's dynamic invocation support not + // only recognizes IReflect/IExpando but actually favors it over DynamicObject. + + if (obj is IReflect reflect) + { + reflect.InvokeMember(Name, BindingFlags.SetField, null, obj, new[] { value }, null, culture, null); + return; + } + + throw new InvalidOperationException("Invalid field assignment"); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return ArrayHelpers.GetEmptyArray(); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + #endregion + } + + #endregion + + #region Nested type: Method + + private sealed class Method : MethodInfo + { + public Method(string name) + { + Name = name; + } + + #region MethodInfo overrides + + public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotImplementedException(); + + public override MethodAttributes Attributes => throw new NotImplementedException(); + + public override RuntimeMethodHandle MethodHandle => throw new NotImplementedException(); + + public override Type DeclaringType => throw new NotImplementedException(); + + public override string Name { get; } + + public override Type ReflectedType => throw new NotImplementedException(); + + public override MethodInfo GetBaseDefinition() + { + throw new NotImplementedException(); + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + throw new NotImplementedException(); + } + + public override ParameterInfo[] GetParameters() + { + return ArrayHelpers.GetEmptyArray(); + } + + public override object Invoke(object obj, BindingFlags invokeFlags, Binder binder, object[] args, CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return ArrayHelpers.GetEmptyArray(); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + #endregion + } + + #endregion + + #region Nested type: Property + + private sealed class Property : PropertyInfo + { + public Property(string name) + { + Name = name; + } + + #region PropertyInfo overrides + + public override PropertyAttributes Attributes => throw new NotImplementedException(); + + public override bool CanRead => throw new NotImplementedException(); + + public override bool CanWrite => throw new NotImplementedException(); + + public override Type PropertyType => throw new NotImplementedException(); + + public override Type DeclaringType => throw new NotImplementedException(); + + public override string Name { get; } + + public override Type ReflectedType => throw new NotImplementedException(); + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + throw new NotImplementedException(); + } + + public override MethodInfo GetGetMethod(bool nonPublic) + { + throw new NotImplementedException(); + } + + public override ParameterInfo[] GetIndexParameters() + { + return ArrayHelpers.GetEmptyArray(); + } + + public override MethodInfo GetSetMethod(bool nonPublic) + { + throw new NotImplementedException(); + } + + public override object GetValue(object obj, BindingFlags invokeFlags, Binder binder, object[] index, CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override void SetValue(object obj, object value, BindingFlags invokeFlags, Binder binder, object[] index, CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + return ArrayHelpers.GetEmptyArray(); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + #endregion + } + + #endregion + + // ReSharper restore ClassNeverInstantiated.Local + + #region Nested type: MemberMapBase + + private class MemberMapBase + { + protected const int CompactionThreshold = 1024 * 1024; + protected static readonly TimeSpan CompactionInterval = TimeSpan.FromMinutes(5); + } + + #endregion + + #region Nested type: MemberMapImpl + + private sealed class MemberMapImpl : MemberMapBase where T : MemberInfo + { + private readonly Dictionary map = new Dictionary(); + private DateTime lastCompactionTime = DateTime.MinValue; + + public T GetMember(string name) + { + lock (map) + { + var result = GetMemberInternal(name); + CompactIfNecessary(); + return result; + } + } + + public T[] GetMembers(string[] names) + { + lock (map) + { + var result = names.Select(GetMemberInternal).ToArray(); + CompactIfNecessary(); + return result; + } + } + + private T GetMemberInternal(string name) + { + T member; + + if (map.TryGetValue(name, out var weakRef)) + { + member = weakRef.Target as T; + if (member == null) + { + member = (T)typeof(T).CreateInstance(name); + weakRef.Target = member; + } + } + else + { + member = (T)typeof(T).CreateInstance(name); + map.Add(name, new WeakReference(member)); + } + + return member; + } + + private void CompactIfNecessary() + { + if (map.Count >= CompactionThreshold) + { + var now = DateTime.UtcNow; + if ((lastCompactionTime + CompactionInterval) <= now) + { + map.Where(pair => !pair.Value.IsAlive).ToList().ForEach(pair => map.Remove(pair.Key)); + lastCompactionTime = now; + } + } + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/MemberMap.cs.meta b/Unity/Package/Runtime/Util/MemberMap.cs.meta new file mode 100644 index 000000000..a73c9d49f --- /dev/null +++ b/Unity/Package/Runtime/Util/MemberMap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 755b320a13624c84eaff5dc16f1efaf4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/MiscHelpers.cs b/Unity/Package/Runtime/Util/MiscHelpers.cs new file mode 100644 index 000000000..45ce56566 --- /dev/null +++ b/Unity/Package/Runtime/Util/MiscHelpers.cs @@ -0,0 +1,608 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ClearScript.Properties; + +namespace Microsoft.ClearScript.Util +{ + internal static class MiscHelpers + { + #region COM helpers + + private static readonly Regex dispIDNameRegex = new Regex(@"^\[DISPID=(-?[0-9]+)\]$"); + + public static object CreateCOMObject(string progID, string serverName) + { + return Activator.CreateInstance(GetCOMType(progID, serverName)); + } + + public static object CreateCOMObject(Guid clsid, string serverName) + { + return Activator.CreateInstance(GetCOMType(clsid, serverName)); + } + + public static bool TryCreateCOMObject(string progID, string serverName, out T obj) where T : class + { + if (!TryGetCOMType(progID, serverName, out var type)) + { + obj = null; + return false; + } + + return Try(out obj, () => Activator.CreateInstance(type) as T) && (obj != null); + } + + public static bool TryCreateCOMObject(Guid clsid, string serverName, out T obj) where T : class + { + if (!TryGetCOMType(clsid, serverName, out var type)) + { + obj = null; + return false; + } + + return Try(out obj, () => Activator.CreateInstance(type) as T) && (obj != null); + } + + public static Type GetCOMType(string progID, string serverName) + { + VerifyNonBlankArgument(progID, nameof(progID), "Invalid programmatic identifier (ProgID)"); + + if (!TryGetCOMType(progID, serverName, out var type)) + { + throw new TypeLoadException(FormatInvariant("Could not find a registered class for '{0}'", progID)); + } + + return type; + } + + public static Type GetCOMType(Guid clsid, string serverName) + { + if (!TryGetCOMType(clsid, serverName, out var type)) + { + throw new TypeLoadException(FormatInvariant("Could not find a registered class for '{0}'", clsid.ToString("B"))); + } + + return type; + } + + public static bool TryGetCOMType(string progID, string serverName, out Type type) + { + type = Guid.TryParseExact(progID, "B", out var clsid) ? Type.GetTypeFromCLSID(clsid, serverName) : Type.GetTypeFromProgID(progID, serverName); + return type != null; + } + + public static bool TryGetCOMType(Guid clsid, string serverName, out Type type) + { + type = Type.GetTypeFromCLSID(clsid, serverName); + return type != null; + } + + public static string GetDispIDName(int dispid) + { + return FormatInvariant("[DISPID={0}]", dispid); + } + + public static bool IsDispIDName(this string name, out int dispid) + { + var match = dispIDNameRegex.Match(name); + if (match.Success && int.TryParse(match.Groups[1].Value, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out dispid)) + { + return true; + } + + dispid = 0; + return false; + } + + #endregion + + #region argument helpers + + public static void VerifyNonNullArgument(object value, string name) + { + if (value == null) + { + throw new ArgumentNullException(name); + } + } + + public static void VerifyNonBlankArgument(string value, string name, string message) + { + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException(message, name); + } + } + + #endregion + + #region string helpers + + private static readonly char[] searchPathSeparators = { ';' }; + + public static string EnsureNonBlank(string input, string alternate) + { + Debug.Assert(!string.IsNullOrWhiteSpace(alternate)); + return string.IsNullOrWhiteSpace(input) ? alternate : input; + } + + public static string FormatInvariant(string format, params object[] args) + { + return string.Format(CultureInfo.InvariantCulture, format, args); + } + + public static StringBuilder AppendInvariant(this StringBuilder builder, string format, params object[] args) + { + return builder.AppendFormat(CultureInfo.InvariantCulture, format, args); + } + + public static string FormatCode(string code) + { + var lines = (code ?? string.Empty).Replace("\r\n", "\n").Split('\n'); + + lines = lines.SkipWhile(string.IsNullOrWhiteSpace).Reverse().SkipWhile(string.IsNullOrWhiteSpace).Reverse().ToArray(); + if (lines.Length > 0) + { + var firstLine = lines[0]; + for (var indentLength = firstLine.TakeWhile(char.IsWhiteSpace).Count(); indentLength > 0; indentLength--) + { + var indent = firstLine.Substring(0, indentLength); + if (lines.Skip(1).All(line => string.IsNullOrWhiteSpace(line) || line.StartsWith(indent, StringComparison.Ordinal))) + { + lines = lines.Select(line => string.IsNullOrWhiteSpace(line) ? string.Empty : line.Substring(indent.Length)).ToArray(); + break; + } + } + } + + return string.Join("\n", lines) + '\n'; + } + + public static string GetUrlOrPath(Uri uri, string alternate) + { + Debug.Assert(alternate != null); + + if (uri == null) + { + return alternate; + } + + if (!uri.IsAbsoluteUri) + { + return uri.ToString(); + } + + if (uri.IsFile) + { + return uri.LocalPath; + } + + return uri.AbsoluteUri; + } + + public static string ToQuotedJson(this string value) + { + var builder = new StringBuilder(); + builder.Append('\"'); + + foreach (var ch in value) + { + switch (ch) + { + case '\"': + builder.Append("\\\""); + break; + + case '\\': + builder.Append("\\\\"); + break; + + default: + builder.Append(ch); + break; + } + } + + builder.Append('\"'); + return builder.ToString(); + } + + public static UIntPtr GetDigest(this string code) + { + return (UIntPtr.Size == 4) ? (UIntPtr)code.GetDigestAsUInt32() : (UIntPtr)code.GetDigestAsUInt64(); + } + + public static uint GetDigestAsUInt32(this string code) + { + var digest = 2166136261U; + const uint prime = 16777619U; + + unchecked + { + var bytes = Encoding.Unicode.GetBytes(code); + for (var index = 0; index < bytes.Length; index++) + { + digest ^= bytes[index]; + digest *= prime; + } + } + + return digest; + } + + public static ulong GetDigestAsUInt64(this string code) + { + var digest = 14695981039346656037UL; + const ulong prime = 1099511628211UL; + + var bytes = Encoding.Unicode.GetBytes(code); + for (var index = 0; index < bytes.Length; index++) + { + digest ^= bytes[index]; + digest *= prime; + } + + return digest; + } + + public static IEnumerable SplitSearchPath(this string searchPath) + { + return searchPath.Split(searchPathSeparators, StringSplitOptions.RemoveEmptyEntries).Distinct(StringComparer.OrdinalIgnoreCase); + } + + public static StringComparison GetMemberNameComparison(this BindingFlags bindFlags) + { + return bindFlags.HasFlag(BindingFlags.IgnoreCase) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + } + + public static StringComparer GetMemberNameComparer(this BindingFlags bindFlags) + { + return bindFlags.HasFlag(BindingFlags.IgnoreCase) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; + } + + #endregion + + #region numeric index helpers + + public static bool TryGetNumericIndex(object arg, out int index) + { + if (arg != null) + { + switch (Type.GetTypeCode(arg.GetType())) + { + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + index = Convert.ToInt32(arg); + return true; + } + } + + index = -1; + return false; + } + + public static bool TryGetNumericIndex(object arg, out long index) + { + if (arg != null) + { + switch (Type.GetTypeCode(arg.GetType())) + { + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + index = Convert.ToInt64(arg); + return true; + } + } + + index = -1; + return false; + } + + #endregion + + #region simplified exception handling + + public static bool Try(Action action) + { + try + { + action(); + return true; + } + catch + { + return false; + } + } + + public static bool Try(out T result, Func func) + { + try + { + result = func(); + return true; + } + catch + { + result = default; + return false; + } + } + + public static async Task TryAsync(Task task) + { + try + { + await task.ConfigureAwait(false); + return true; + } + catch + { + return false; + } + } + + public static async Task TryAsync(Holder holder, Task task) + { + try + { + holder.Value = await task.ConfigureAwait(false); + return true; + } + catch + { + return false; + } + } + + #endregion + + #region primitive marshaling + + public static bool TryMarshalPrimitiveToHost(object obj, bool disableFloatNarrowing, out object result) + { + if (obj is IConvertible convertible) + { + switch (convertible.GetTypeCode()) + { + case TypeCode.String: + case TypeCode.Boolean: + result = obj; + return true; + + case TypeCode.Double: + case TypeCode.Single: + result = MarshalDoubleToHost(convertible.ToDouble(CultureInfo.InvariantCulture), disableFloatNarrowing); + return true; + + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Char: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Decimal: + result = obj; + return true; + } + } + + result = null; + return false; + } + + public static object MarshalDoubleToHost(double value, bool disableFloatNarrowing) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + + if (Math.Round(value) == value) + { + const double maxIntInDouble = (1L << 53) - 1; + if (Math.Abs(value) <= maxIntInDouble) + { + var longValue = Convert.ToInt64(value); + if ((longValue >= int.MinValue) && (longValue <= int.MaxValue)) + { + return (int)longValue; + } + + return longValue; + } + } + else if (!disableFloatNarrowing) + { + var floatValue = Convert.ToSingle(value); + if (value == floatValue) + { + return floatValue; + } + } + + return value; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + #endregion + + #region miscellaneous + + public static T Exchange(ref T target, T value) + { + var oldValue = target; + target = value; + return oldValue; + } + + public static void QueueNativeCallback(INativeCallback callback) + { + ThreadPool.QueueUserWorkItem(_ => + { + using (callback) + { + Try(callback.Invoke); + } + + // The above code appears to be problematic on some .NET runtimes, intermittently + // triggering premature finalization of the callback. That can lead to a crash if + // the callback's finalizer ends up racing against its Dispose method. The call + // below should prevent this condition in all cases. + // + // UPDATE: The observed behavior is actually documented. As Dispose is invoked via + // the callback's only reference, the callback may become eligible for finalization + // during the call. Typically, Dispose invokes GC.SuppressFinalize just before + // exiting, which, in addition to canceling finalization, extends the object's + // lifetime until Dispose has done its job. The callback here is unusual in that it + // requires finalization regardless of disposal, so the correct fix is for Dispose + // to invoke GC.KeepAlive as its final step. The original fix is retained here for + // regression avoidance. + + GC.KeepAlive(callback); + }); + } + + public static Random CreateSeededRandom() + { + return new Random(Convert.ToUInt32(DateTime.Now.Ticks.ToUnsigned() & 0x00000000FFFFFFFFUL).ToSigned()); + } + + public static async Task CreateLockScopeAsync(this SemaphoreSlim semaphore) + { + await semaphore.WaitAsync().ConfigureAwait(false); + return Scope.Create(null, () => semaphore.Release()); + } + + public static byte[] ReadToEnd(this Stream stream) + { + using (var memoryStream = new MemoryStream()) + { + stream.CopyTo(memoryStream); + return memoryStream.ToArray(); + } + } + + public static string GetTextContents(this Document document) + { + if (document is StringDocument stringDocument) + { + return stringDocument.StringContents; + } + + using (var reader = new StreamReader(document.Contents, document.Encoding ?? Encoding.UTF8)) + { + return reader.ReadToEnd(); + } + } + + public static void AssertUnreachable() + { + Debug.Assert(false, "Entered code block presumed unreachable."); + } + + public static string GetLocalDataRootPath(out bool usingAppPath) + { + var basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + if (string.IsNullOrWhiteSpace(basePath)) + { + basePath = AppDomain.CurrentDomain.BaseDirectory; + usingAppPath = true; + } + else + { + usingAppPath = false; + } + + return GetLocalDataRootPath(basePath); + } + + public static string GetLocalDataRootPath(string basePath) + { + var path = Path.Combine(basePath, "Microsoft", "ClearScript", ClearScriptVersion.Triad, Environment.Is64BitProcess ? "x64" : "x86"); + + if (Try(out var fullPath, () => Path.GetFullPath(path))) + { + return fullPath; + } + + return path; + } + + public static bool PlatformIsWindows() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + } + + public static bool PlatformIsLinux() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + } + + public static bool PlatformIsOSX() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + } + + public static bool ProcessorArchitectureIsIntel() + { + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.X64: + case Architecture.X86: + return true; + + default: + return false; + } + } + + public static bool ProcessorArchitectureIsArm() + { + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.Arm: + case Architecture.Arm64: + return true; + + default: + return false; + } + } + + public static object GetObjectForVariant(IntPtr pVariant) + { + var result = Marshal.GetObjectForNativeVariant(pVariant); + + if ((result == null) && (Marshal.ReadInt16(pVariant) == (short)VarEnum.VT_BSTR)) + { + return string.Empty; + } + + return result; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/MiscHelpers.cs.meta b/Unity/Package/Runtime/Util/MiscHelpers.cs.meta new file mode 100644 index 000000000..a1b830627 --- /dev/null +++ b/Unity/Package/Runtime/Util/MiscHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82e1f6d64aa2aa7489ee800b9fab9aeb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/NativeCallbackTimer.cs b/Unity/Package/Runtime/Util/NativeCallbackTimer.cs new file mode 100644 index 000000000..66085cb52 --- /dev/null +++ b/Unity/Package/Runtime/Util/NativeCallbackTimer.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Threading; + +namespace Microsoft.ClearScript.Util +{ + internal sealed class NativeCallbackTimer : IDisposable + { + private readonly Timer timer; + private readonly INativeCallback callback; + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + public NativeCallbackTimer(int dueTime, int period, INativeCallback callback) + { + this.callback = callback; + timer = new Timer(OnTimer, null, Timeout.Infinite, Timeout.Infinite); + + if ((dueTime != Timeout.Infinite) || (period != Timeout.Infinite)) + { + timer.Change(dueTime, period); + } + } + + public bool Change(int dueTime, int period) + { + if (!disposedFlag.IsSet) + { + if (MiscHelpers.Try(out var result, () => timer.Change(dueTime, period))) + { + return result; + } + } + + return false; + } + + private void OnTimer(object _) + { + if (!disposedFlag.IsSet) + { + MiscHelpers.Try(callback.Invoke); + } + } + + public void Dispose() + { + if (disposedFlag.Set()) + { + timer.Dispose(); + callback.Dispose(); + } + } + } +} diff --git a/Unity/Package/Runtime/Util/NativeCallbackTimer.cs.meta b/Unity/Package/Runtime/Util/NativeCallbackTimer.cs.meta new file mode 100644 index 000000000..fee02a9f3 --- /dev/null +++ b/Unity/Package/Runtime/Util/NativeCallbackTimer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db6c2d213e82f694180f54302bc5c6c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/NativeMethods.cs b/Unity/Package/Runtime/Util/NativeMethods.cs new file mode 100644 index 000000000..2838915fe --- /dev/null +++ b/Unity/Package/Runtime/Util/NativeMethods.cs @@ -0,0 +1,345 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util +{ + internal static class NativeMethods + { + public static IntPtr LoadLibrary(string path) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.LoadLibraryW(path); + } + + if (MiscHelpers.PlatformIsLinux()) + { + return NativeLinuxMethods.LoadLibrary(path); + } + + if (MiscHelpers.PlatformIsOSX()) + { + return NativeOSXMethods.LoadLibrary(path); + } + + throw new PlatformNotSupportedException(); + } + + public static bool FreeLibrary(IntPtr hLibrary) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.FreeLibrary(hLibrary); + } + + if (MiscHelpers.PlatformIsLinux()) + { + return NativeLinuxMethods.FreeLibrary(hLibrary) == 0; + } + + if (MiscHelpers.PlatformIsOSX()) + { + return NativeOSXMethods.FreeLibrary(hLibrary) == 0; + } + + throw new PlatformNotSupportedException(); + } + + public static string GetLoadLibraryErrorMessage() + { + if (MiscHelpers.PlatformIsWindows()) + { + return new Win32Exception().Message; + } + + if (MiscHelpers.PlatformIsLinux()) + { + return Marshal.PtrToStringAnsi(NativeLinuxMethods.GetLoadLibraryErrorMessage()); + } + + if (MiscHelpers.PlatformIsOSX()) + { + return Marshal.PtrToStringAnsi(NativeOSXMethods.GetLoadLibraryErrorMessage()); + } + + throw new PlatformNotSupportedException(); + } + + public static uint CLSIDFromProgID(string progID, out Guid clsid) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.CLSIDFromProgID(progID, out clsid); + } + + throw new PlatformNotSupportedException(); + } + + public static uint ProgIDFromCLSID(ref Guid clsid, out string progID) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.ProgIDFromCLSID(ref clsid, out progID); + } + + throw new PlatformNotSupportedException(); + } + + public static uint CoCreateInstance(ref Guid clsid, IntPtr pOuter, uint clsContext, ref Guid iid, out IntPtr pInterface) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.CoCreateInstance(ref clsid, pOuter, clsContext, ref iid, out pInterface); + } + + throw new PlatformNotSupportedException(); + } + + public static void VariantInit(IntPtr pVariant) + { + if (MiscHelpers.PlatformIsWindows()) + { + NativeWindowsMethods.VariantInit(pVariant); + } + else + { + throw new PlatformNotSupportedException(); + } + } + + public static uint VariantClear(IntPtr pVariant) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.VariantClear(pVariant); + } + + throw new PlatformNotSupportedException(); + } + + public static IntPtr HeapCreate(uint options, UIntPtr initialSize, UIntPtr maximumSize) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.HeapCreate(options, initialSize, maximumSize); + } + + throw new PlatformNotSupportedException(); + } + + public static IntPtr HeapAlloc(IntPtr hHeap, uint flags, UIntPtr size) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.HeapAlloc(hHeap, flags, size); + } + + throw new PlatformNotSupportedException(); + } + + public static bool HeapFree(IntPtr hHeap, uint flags, IntPtr pBlock) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.HeapFree(hHeap, flags, pBlock); + } + + throw new PlatformNotSupportedException(); + } + + public static bool HeapDestroy(IntPtr hHeap) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.HeapDestroy(hHeap); + } + + throw new PlatformNotSupportedException(); + } + + public static bool VirtualProtect(IntPtr pBlock, UIntPtr size, uint newProtect, out uint oldProtect) + { + if (MiscHelpers.PlatformIsWindows()) + { + return NativeWindowsMethods.VirtualProtect(pBlock, size, newProtect, out oldProtect); + } + + throw new PlatformNotSupportedException(); + } + + #region Nested type: NativeWindowsMethods + + private static class NativeWindowsMethods + { + // ReSharper disable MemberHidesStaticFromOuterClass + + [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] + public static extern IntPtr LoadLibraryW( + [In] [MarshalAs(UnmanagedType.LPWStr)] string path + ); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FreeLibrary( + [In] IntPtr hLibrary + ); + + [DllImport("ole32.dll", ExactSpelling = true)] + public static extern uint CLSIDFromProgID( + [In] [MarshalAs(UnmanagedType.LPWStr)] string progID, + [Out] out Guid clsid + ); + + [DllImport("ole32.dll")] + public static extern uint ProgIDFromCLSID( + [In] ref Guid clsid, + [Out] [MarshalAs(UnmanagedType.LPWStr)] out string progID + ); + + [DllImport("ole32.dll", ExactSpelling = true)] + public static extern uint CoCreateInstance( + [In] ref Guid clsid, + [In] IntPtr pOuter, + [In] uint clsContext, + [In] ref Guid iid, + [Out] out IntPtr pInterface + ); + + [DllImport("oleaut32.dll", ExactSpelling = true)] + public static extern void VariantInit( + [In] IntPtr pVariant + ); + + [DllImport("oleaut32.dll", ExactSpelling = true)] + public static extern uint VariantClear( + [In] IntPtr pVariant + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr HeapCreate( + [In] uint options, + [In] UIntPtr initialSize, + [In] UIntPtr maximumSize + ); + + [DllImport("kernel32.dll", SetLastError = false)] + public static extern IntPtr HeapAlloc( + [In] IntPtr hHeap, + [In] uint flags, + [In] UIntPtr size + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool HeapFree( + [In] IntPtr hHeap, + [In] uint flags, + [In] IntPtr pBlock + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool HeapDestroy( + [In] IntPtr hHeap + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool VirtualProtect( + [In] IntPtr pBlock, + [In] UIntPtr size, + [In] uint newProtect, + [Out] out uint oldProtect + ); + + // ReSharper restore MemberHidesStaticFromOuterClass + } + + #endregion + + #region Nested type: NativeLinuxMethods + + private static class NativeLinuxMethods + { + // ReSharper disable MemberHidesStaticFromOuterClass + + [Flags] + public enum LoadLibraryFlags + { + // ReSharper disable UnusedMember.Local + + None = 0, + Lazy = 0x0001, + Now = 0x0002, + BindingMask = 0x0003, + NoLoad = 0x0004, + DeepBind = 0x0008, + Local = None, + Global = 0x0100, + NoDelete = 0x1000 + + // ReSharper restore UnusedMember.Local + } + + [DllImport("libdl.so.2", EntryPoint = "dlopen")] + public static extern IntPtr LoadLibrary( + [In] [MarshalAs(UnmanagedType.LPStr)] string path, + [In] LoadLibraryFlags flags = LoadLibraryFlags.Now | LoadLibraryFlags.Global + ); + + [DllImport("libdl.so.2", EntryPoint = "dlclose")] + public static extern int FreeLibrary( + [In] IntPtr hLibrary + ); + + [DllImport("libdl.so.2", EntryPoint = "dlerror")] + public static extern IntPtr GetLoadLibraryErrorMessage(); + + // ReSharper restore MemberHidesStaticFromOuterClass + } + + #endregion + + #region Nested type: NativeOSXMethods + + private static class NativeOSXMethods + { + // ReSharper disable MemberHidesStaticFromOuterClass + + [Flags] + public enum LoadLibraryFlags + { + // ReSharper disable UnusedMember.Local + + None = 0, + Lazy = 0x01, + Now = 0x02, + Local = 0x04, + Global = 0x08, + NoLoad = 0x10, + NoDelete = 0x80 + + // ReSharper restore UnusedMember.Local + } + + [DllImport("libdl.dylib", EntryPoint = "dlopen")] + public static extern IntPtr LoadLibrary( + [In] [MarshalAs(UnmanagedType.LPStr)] string path, + [In] LoadLibraryFlags flags = LoadLibraryFlags.Now | LoadLibraryFlags.Global + ); + + [DllImport("libdl.dylib", EntryPoint = "dlclose")] + public static extern int FreeLibrary( + [In] IntPtr hLibrary + ); + + [DllImport("libdl.dylib", EntryPoint = "dlerror")] + public static extern IntPtr GetLoadLibraryErrorMessage(); + + // ReSharper restore MemberHidesStaticFromOuterClass + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/NativeMethods.cs.meta b/Unity/Package/Runtime/Util/NativeMethods.cs.meta new file mode 100644 index 000000000..9ced26cd6 --- /dev/null +++ b/Unity/Package/Runtime/Util/NativeMethods.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afb2ed7211c2134418b2129d279bbff7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Nonexistent.cs b/Unity/Package/Runtime/Util/Nonexistent.cs new file mode 100644 index 000000000..f6576e6fb --- /dev/null +++ b/Unity/Package/Runtime/Util/Nonexistent.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal sealed class Nonexistent + { + public static readonly Nonexistent Value = new Nonexistent(); + + private Nonexistent() + { + } + } +} diff --git a/Unity/Package/Runtime/Util/Nonexistent.cs.meta b/Unity/Package/Runtime/Util/Nonexistent.cs.meta new file mode 100644 index 000000000..ffa38c6b6 --- /dev/null +++ b/Unity/Package/Runtime/Util/Nonexistent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2c766d33f2b12947998d98f00f63a3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs b/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs new file mode 100644 index 000000000..871673450 --- /dev/null +++ b/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Globalization; +using Microsoft.Win32; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class ObjectHelpers + { + private static bool GetPrimaryInteropAssembly(Guid libid, int major, int minor, out string name, out string codeBase) + { +#if UNITY_5_3_OR_NEWER // There is no just "is Unity" symbol. + throw new NotSupportedException("What the hell are you doing with COM in a Unity game??"); +#else + name = null; + codeBase = null; + + using (var containerKey = Registry.ClassesRoot.OpenSubKey("TypeLib", false)) + { + if (containerKey != null) + { + var typeLibName = "{" + libid.ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; + using (var typeLibKey = containerKey.OpenSubKey(typeLibName)) + { + if (typeLibKey != null) + { + var versionName = major.ToString("x", CultureInfo.InvariantCulture) + "." + minor.ToString("x", CultureInfo.InvariantCulture); + using (var versionKey = typeLibKey.OpenSubKey(versionName, false)) + { + if (versionKey != null) + { + name = (string)versionKey.GetValue("PrimaryInteropAssemblyName"); + codeBase = (string)versionKey.GetValue("PrimaryInteropAssemblyCodeBase"); + } + } + } + } + } + } + + return name != null; +#endif + } + } +} diff --git a/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs.meta b/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs.meta new file mode 100644 index 000000000..269a20452 --- /dev/null +++ b/Unity/Package/Runtime/Util/ObjectHelpers.Common.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2928f8053d0b2c49b6425ef2605dc79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/ObjectHelpers.cs b/Unity/Package/Runtime/Util/ObjectHelpers.cs new file mode 100644 index 000000000..6ef28333a --- /dev/null +++ b/Unity/Package/Runtime/Util/ObjectHelpers.cs @@ -0,0 +1,358 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.ClearScript.Util.COM; +using TYPEFLAGS = System.Runtime.InteropServices.ComTypes.TYPEFLAGS; +using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class ObjectHelpers + { + private static readonly object[] zeroes = + { + (sbyte)0, + (byte)0, + (short)0, + (ushort)0, + 0, + 0U, + 0L, + 0UL, + IntPtr.Zero, + UIntPtr.Zero, + 0.0f, + 0.0d, + 0.0m + }; + + public static bool IsZero(this object value) => Array.IndexOf(zeroes, value) >= 0; + + public static bool IsWholeNumber(this object value) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + + if (value == null) + { + return false; + } + + if (value.GetType().IsIntegral()) + { + return true; + } + + if (value is float floatValue) + { + return Math.Round(floatValue) == floatValue; + } + + if (value is double doubleValue) + { + return Math.Round(doubleValue) == doubleValue; + } + + if (value is decimal decimalValue) + { + return Math.Round(decimalValue) == decimalValue; + } + + return false; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + public static Type GetTypeOrTypeInfo(this object value) + { + if (!MiscHelpers.PlatformIsWindows()) + { + return value.GetType(); + } + + var type = value.GetType(); + IDispatch dispatch = null; + + Type typeInfo = null; + TYPEKIND typeInfoKind = 0; + TYPEFLAGS typeInfoFlags = 0; + + if (type.IsUnknownCOMObject()) + { + // This appears to be a generic COM object with no specific type information. + // Attempt to acquire COM type information via IDispatch or IProvideClassInfo. + + dispatch = value as IDispatch; + if (dispatch != null) + { + var tempTypeInfo = dispatch.GetTypeInfo(); + if (tempTypeInfo != null) + { + typeInfo = GetTypeForTypeInfo(tempTypeInfo); + typeInfoKind = tempTypeInfo.GetKind(); + typeInfoFlags = tempTypeInfo.GetFlags(); + } + } + + if (typeInfo == null) + { + if (value is IProvideClassInfo provideClassInfo) + { + if (HResult.Succeeded(provideClassInfo.GetClassInfo(out var tempTypeInfo))) + { + typeInfo = GetTypeForTypeInfo(tempTypeInfo); + typeInfoKind = tempTypeInfo.GetKind(); + typeInfoFlags = tempTypeInfo.GetFlags(); + } + } + } + } + + if (typeInfo != null) + { + // If the COM type is a dispatch-only interface, use it. Such interfaces typically + // aren't exposed via QueryInterface(), so there's no way to validate them anyway. + + if ((dispatch != null) && (typeInfoKind == TYPEKIND.TKIND_DISPATCH) && typeInfoFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FDISPATCHABLE) && !typeInfoFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FDUAL)) + { + return typeInfo; + } + + // COM type information acquired in this manner may not actually be valid for the + // original object. In some cases the original object implements a base interface. + + if (typeInfo.IsInstanceOfType(value)) + { + return typeInfo; + } + + foreach (var interfaceType in typeInfo.GetInterfaces()) + { + if (interfaceType.IsInstanceOfType(value)) + { + return interfaceType; + } + } + } + + return type; + } + + private static Type GetTypeForTypeInfo(ITypeInfo typeInfo) + { + // ReSharper disable EmptyGeneralCatchClause + + try + { + var typeLib = typeInfo.GetContainingTypeLib(out var index); + + var assembly = LoadPrimaryInteropAssembly(typeLib); + if (assembly != null) + { + var name = typeInfo.GetManagedName(); + var guid = typeInfo.GetGuid(); + + var type = assembly.GetType(name, false, true); + if ((type != null) && (type.GUID == guid)) + { + return type; + } + + var types = assembly.GetAllTypes().ToArray(); + if ((index >= 0) && (index < types.Length)) + { + type = types[index]; + if ((type.GUID == guid) && (type.FullName == name)) + { + return type; + } + } + + type = types.FirstOrDefault(testType => (testType.GUID == guid) && (testType.FullName.Equals(name, StringComparison.OrdinalIgnoreCase))); + if (type != null) + { + return type; + } + } + + return typeInfo.GetManagedType(); + } + catch + { + } + + return null; + + // ReSharper restore EmptyGeneralCatchClause + } + + private static Assembly LoadPrimaryInteropAssembly(ITypeLib typeLib) + { + if (typeLib == null) + { + return null; + } + + // ReSharper disable EmptyGeneralCatchClause + + try + { + using (var attrScope = typeLib.CreateAttrScope()) + { + if (GetPrimaryInteropAssembly(attrScope.Value.guid, attrScope.Value.wMajorVerNum, attrScope.Value.wMinorVerNum, out var name, out var codeBase)) + { + return Assembly.Load(new AssemblyName(name) { CodeBase = codeBase }); + } + } + } + catch + { + } + + return null; + + // ReSharper restore EmptyGeneralCatchClause + } + + public static string GetFriendlyName(this object value) + { + return value.GetFriendlyName(null); + } + + public static string GetFriendlyName(this object value, Type type) + { + if (type == null) + { + if (value == null) + { + return "[null]"; + } + + type = value.GetType(); + } + + if (type.IsArray && (value != null)) + { + var array = (Array)value; + var dimensions = Enumerable.Range(0, type.GetArrayRank()); + var lengths = string.Join(",", dimensions.Select(array.GetLength)); + return MiscHelpers.FormatInvariant("{0}[{1}]", type.GetElementType().GetFriendlyName(), lengths); + } + + if (type.IsUnknownCOMObject()) + { + if (value is IDispatch dispatch) + { + var typeInfo = dispatch.GetTypeInfo(); + if (typeInfo != null) + { + return typeInfo.GetName(); + } + } + } + + return type.GetFriendlyName(); + } + + public static T DynamicCast(this object value) + { + return DynamicCaster.Cast(value); + } + + public static object ToDynamicResult(this object result, ScriptEngine engine) + { + if (result is Nonexistent) + { + return Undefined.Value; + } + + if ((result is HostTarget) || (result is IPropertyBag)) + { + // Returning an instance of HostTarget (an internal type) isn't likely to be + // useful. Wrapping it in a dynamic object makes sense in this context. Wrapping + // a property bag allows it to participate in dynamic invocation chaining, which + // may be useful when dealing with things like host type collections. HostItem + // supports dynamic conversion, so the client can unwrap the object if necessary. + + return HostItem.Wrap(engine, result); + } + + return result; + } + + #region Nested type: IProvideClassInfo + + [ComImport] + [Guid("b196b283-bab4-101a-b69c-00aa00341d07")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IProvideClassInfo + { + [PreserveSig] + int GetClassInfo( + [Out] [MarshalAs(UnmanagedType.Interface)] out ITypeInfo typeInfo + ); + } + + #endregion + + #region Nested type: DynamicCaster + + private static class DynamicCaster + { + public static T Cast(object value) + { + // ReSharper disable EmptyGeneralCatchClause + + try + { + if (!typeof(T).IsValueType) + { + return (T)value; + } + + if (typeof(T).IsEnum) + { + return (T)Enum.ToObject(typeof(T), value); + } + + if (typeof(T).IsNullable()) + { + return (T)CastToNullable(value); + } + + if (value is IConvertible) + { + return (T)Convert.ChangeType(value, typeof(T)); + } + + return (T)value; + } + catch + { + } + + return (T)(dynamic)value; + + // ReSharper restore EmptyGeneralCatchClause + } + + private static object CastToNullable(object value) + { + if (value != null) + { + var valueCastType = typeof(DynamicCaster<>).MakeGenericType(Nullable.GetUnderlyingType(typeof(T))); + value = valueCastType.InvokeMember("Cast", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new[] { value }); + return typeof(T).CreateInstance(value); + } + + return null; + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/ObjectHelpers.cs.meta b/Unity/Package/Runtime/Util/ObjectHelpers.cs.meta new file mode 100644 index 000000000..a8bbfcd35 --- /dev/null +++ b/Unity/Package/Runtime/Util/ObjectHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25973d570f9e641428ed7a09d507cb02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/OneWayFlag.cs b/Unity/Package/Runtime/Util/OneWayFlag.cs new file mode 100644 index 000000000..9b225fcda --- /dev/null +++ b/Unity/Package/Runtime/Util/OneWayFlag.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Threading; + +namespace Microsoft.ClearScript.Util +{ + internal sealed class OneWayFlag + { + private bool isSet; + + public bool IsSet => isSet; + + public bool Set() + { + return MiscHelpers.Exchange(ref isSet, true) == false; + } + } + + internal sealed class InterlockedOneWayFlag + { + private int isSet; + + public bool IsSet => isSet != 0; + + public bool Set() + { + return Interlocked.Exchange(ref isSet, 1) == 0; + } + } +} diff --git a/Unity/Package/Runtime/Util/OneWayFlag.cs.meta b/Unity/Package/Runtime/Util/OneWayFlag.cs.meta new file mode 100644 index 000000000..1ebb05604 --- /dev/null +++ b/Unity/Package/Runtime/Util/OneWayFlag.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3501b5982b6d3f74eb372dc0c9a4c4af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Scope.cs b/Unity/Package/Runtime/Util/Scope.cs new file mode 100644 index 000000000..bd9f168d9 --- /dev/null +++ b/Unity/Package/Runtime/Util/Scope.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.Util +{ + internal interface IScope: IDisposable + { + T Value { get; } + } + + internal static class Scope + { + public static IDisposable Create(Action enterAction, Action exitAction) + { + return new ScopeImpl(enterAction, exitAction); + } + + public static IScope Create(Func enterFunc, Action exitAction) + { + return new ScopeImpl(enterFunc, exitAction); + } + + #region Nested type: ScopeImpl + + private sealed class ScopeImpl : IDisposable + { + private readonly Action exitAction; + private readonly OneWayFlag disposedFlag = new OneWayFlag(); + + public ScopeImpl(Action enterAction, Action exitAction) + { + this.exitAction = exitAction; + enterAction?.Invoke(); + } + + #region IDisposable implementation + + public void Dispose() + { + if (disposedFlag.Set()) + { + exitAction?.Invoke(); + } + } + + #endregion + } + + #endregion + + #region Nested type: ScopeImpl + + private sealed class ScopeImpl : IScope + { + private readonly Action exitAction; + private readonly OneWayFlag disposedFlag = new OneWayFlag(); + + public ScopeImpl(Func enterFunc, Action exitAction) + { + this.exitAction = exitAction; + if (enterFunc != null) + { + Value = enterFunc(); + } + } + + #region IScope implementation + + public T Value { get; } + + public void Dispose() + { + if (disposedFlag.Set()) + { + exitAction?.Invoke(Value); + } + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/Scope.cs.meta b/Unity/Package/Runtime/Util/Scope.cs.meta new file mode 100644 index 000000000..a549f10db --- /dev/null +++ b/Unity/Package/Runtime/Util/Scope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d43986a247b01e943868bfffcb72305b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/SocketHelpers.cs b/Unity/Package/Runtime/Util/SocketHelpers.cs new file mode 100644 index 000000000..986750873 --- /dev/null +++ b/Unity/Package/Runtime/Util/SocketHelpers.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.Util +{ + internal static class SocketHelpers + { + public static Task SendStringAsync(this Socket socket, string value, Encoding encoding = null) + { + return socket.SendBytesAsync((encoding ?? Encoding.UTF8).GetBytes(value)); + } + + public static async Task ReceiveLineAsync(this Socket socket, Encoding encoding = null) + { + var lineBytes = new List(1024); + var bytes = new byte[1]; + + while (true) + { + await socket.ReceiveBytesAsync(bytes, 0, 1).ConfigureAwait(false); + + var lastIndex = lineBytes.Count - 1; + if ((lastIndex >= 0) && (lineBytes[lastIndex] == Convert.ToByte('\r')) && (bytes[0] == Convert.ToByte('\n'))) + { + lineBytes.RemoveAt(lastIndex); + break; + } + + lineBytes.Add(bytes[0]); + } + + return (encoding ?? Encoding.UTF8).GetString(lineBytes.ToArray()); + } + + public static Task SendBytesAsync(this Socket socket, byte[] bytes) + { + return socket.SendBytesAsync(bytes, 0, bytes.Length); + } + + public static async Task SendBytesAsync(this Socket socket, byte[] bytes, int offset, int count) + { + while (count > 0) + { + var sentCount = await socket.SendAsync(bytes, offset, count).ConfigureAwait(false); + if (sentCount < 1) + { + throw new IOException("Failed to send data to socket"); + } + + offset += sentCount; + count -= sentCount; + } + } + + public static async Task ReceiveBytesAsync(this Socket socket, int count) + { + var bytes = new byte[count]; + await socket.ReceiveBytesAsync(bytes, 0, count).ConfigureAwait(false); + return bytes; + } + + public static async Task ReceiveBytesAsync(this Socket socket, byte[] bytes, int offset, int count) + { + while (count > 0) + { + var receivedCount = await socket.ReceiveAsync(bytes, offset, count).ConfigureAwait(false); + if (receivedCount < 1) + { + throw new IOException("Failed to receive data from socket"); + } + + offset += receivedCount; + count -= receivedCount; + } + } + + private static Task SendAsync(this Socket socket, byte[] bytes, int offset, int count) + { + return Task.Factory.FromAsync( + (callback, state) => socket.BeginSend(bytes, offset, count, SocketFlags.None, callback, state), + socket.EndSend, + null + ); + } + + private static Task ReceiveAsync(this Socket socket, byte[] bytes, int offset, int count) + { + return Task.Factory.FromAsync( + (callback, state) => socket.BeginReceive(bytes, offset, count, SocketFlags.None, callback, state), + socket.EndReceive, + null + ); + } + } +} diff --git a/Unity/Package/Runtime/Util/SocketHelpers.cs.meta b/Unity/Package/Runtime/Util/SocketHelpers.cs.meta new file mode 100644 index 000000000..e6a70198d --- /dev/null +++ b/Unity/Package/Runtime/Util/SocketHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce4cd84e2f19e0b47937eeebaaf68b24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/SpecialDispIDs.cs b/Unity/Package/Runtime/Util/SpecialDispIDs.cs new file mode 100644 index 000000000..944048cc6 --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialDispIDs.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal static class SpecialDispIDs + { + public const int Default = 0; + public const int Unknown = -1; + public const int StartEnum = Unknown; + public const int PropertyPut = -3; + public const int NewEnum = -4; + public const int This = -613; + public const int GetEnumerator = -1024 * 96; + public const int NewAsyncEnum = -1024 * 256; + } +} diff --git a/Unity/Package/Runtime/Util/SpecialDispIDs.cs.meta b/Unity/Package/Runtime/Util/SpecialDispIDs.cs.meta new file mode 100644 index 000000000..dfc2f6451 --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialDispIDs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91d94a4e3480f8447a750e24035ed575 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/SpecialMemberNames.cs b/Unity/Package/Runtime/Util/SpecialMemberNames.cs new file mode 100644 index 000000000..099a1f95e --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialMemberNames.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal static class SpecialMemberNames + { + public static readonly string Default = MiscHelpers.GetDispIDName(SpecialDispIDs.Default); + public static readonly string NewEnum = MiscHelpers.GetDispIDName(SpecialDispIDs.NewEnum); + public static readonly string NewAsyncEnum = MiscHelpers.GetDispIDName(SpecialDispIDs.NewAsyncEnum); + } +} diff --git a/Unity/Package/Runtime/Util/SpecialMemberNames.cs.meta b/Unity/Package/Runtime/Util/SpecialMemberNames.cs.meta new file mode 100644 index 000000000..92c8930b1 --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialMemberNames.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 674f575543070ce4b90e1b579a07455c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/SpecialParamNames.cs b/Unity/Package/Runtime/Util/SpecialParamNames.cs new file mode 100644 index 000000000..e24419a11 --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialParamNames.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.Util +{ + internal static class SpecialParamNames + { + public static readonly string This = MiscHelpers.GetDispIDName(SpecialDispIDs.This); + } +} diff --git a/Unity/Package/Runtime/Util/SpecialParamNames.cs.meta b/Unity/Package/Runtime/Util/SpecialParamNames.cs.meta new file mode 100644 index 000000000..edbd6221e --- /dev/null +++ b/Unity/Package/Runtime/Util/SpecialParamNames.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81298291ee56a6c4bad289853c9398bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Test.meta b/Unity/Package/Runtime/Util/Test.meta new file mode 100644 index 000000000..776d49b4c --- /dev/null +++ b/Unity/Package/Runtime/Util/Test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cdae5c3802e545d4b9770e4f24eaf425 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs b/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs new file mode 100644 index 000000000..b252b7856 --- /dev/null +++ b/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs @@ -0,0 +1,61 @@ +using System; + +namespace Microsoft.ClearScript.Util.Test +{ + internal class AccessContextTestBase + { + #pragma warning disable 169 // The field 'abc' is never used + #pragma warning disable 67 // Event 'abc' is never invoked + // ReSharper disable UnusedMember.Local + // ReSharper disable UnusedParameter.Local + // ReSharper disable EventNeverSubscribedTo.Local + // ReSharper disable UnusedType.Local + + public AccessContextTestBase() {} + internal AccessContextTestBase(int arg) {} + protected AccessContextTestBase(string arg) {} + protected internal AccessContextTestBase(DateTime arg) {} + private AccessContextTestBase(TimeSpan arg) {} + + public event EventHandler PublicEvent; + internal event EventHandler InternalEvent; + protected event EventHandler ProtectedEvent; + protected internal event EventHandler ProtectedInternalEvent; + private event EventHandler PrivateEvent; + + public string PublicField; + internal string InternalField; + protected string ProtectedField; + protected internal string ProtectedInternalField; + private string privateField; + + public void PublicMethod() {} + internal void InternalMethod() {} + protected void ProtectedMethod() {} + protected internal void ProtectedInternalMethod() {} + private void PrivateMethod() {} + + public string PublicProperty { get; set; } + internal string InternalProperty { get; set; } + protected string ProtectedProperty { get; set; } + protected internal string ProtectedInternalProperty { get; set; } + private string PrivateProperty { get; set; } + + public class PublicNestedType {} + internal sealed class InternalNestedType {} + protected class ProtectedNestedType {} + protected internal sealed class ProtectedInternalNestedType {} + private sealed class PrivateNestedType {} + + // ReSharper restore UnusedType.Local + // ReSharper restore EventNeverSubscribedTo.Local + // ReSharper restore UnusedParameter.Local + // ReSharper restore UnusedMember.Local + #pragma warning restore 67 // Event 'abc' is never invoked + #pragma warning restore 169 // The field 'abc' is never used + } + + internal sealed class AccessContextTestObject : AccessContextTestBase + { + } +} diff --git a/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs.meta b/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs.meta new file mode 100644 index 000000000..d0244b87c --- /dev/null +++ b/Unity/Package/Runtime/Util/Test/AccessContextTestObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d892d09a7489a4444bfa374588f2ee69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs b/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs new file mode 100644 index 000000000..633048d5d --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class TypeHelpers + { + private static string GetFullTypeName(string name, string assemblyName, bool useAssemblyName, int typeArgCount) + { + var fullTypeName = name; + + if (typeArgCount > 0) + { + fullTypeName += MiscHelpers.FormatInvariant("`{0}", typeArgCount); + } + + if (useAssemblyName) + { + if (MiscHelpers.Try(out var assembly, () => Assembly.Load(AssemblyTable.GetFullAssemblyName(assemblyName)))) + { + // ReSharper disable once AccessToModifiedClosure + if (MiscHelpers.Try(out var result, () => assembly.GetType(fullTypeName).AssemblyQualifiedName)) + { + return result; + } + } + + fullTypeName += MiscHelpers.FormatInvariant(", {0}", AssemblyTable.GetFullAssemblyName(assemblyName)); + } + + return fullTypeName; + } + + public static IntPtr GetTypeInfo(this Type type) + { + return IntPtr.Zero; + } + } +} diff --git a/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs.meta b/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs.meta new file mode 100644 index 000000000..b40588f8f --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeHelpers.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22a1d4578f0cd6c42b5a9291d7fc6347 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/TypeHelpers.cs b/Unity/Package/Runtime/Util/TypeHelpers.cs new file mode 100644 index 000000000..835c5d1f9 --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeHelpers.cs @@ -0,0 +1,1404 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript.Util +{ + internal static partial class TypeHelpers + { + private static readonly string[] importDenyList = + { + // ReSharper disable StringLiteralTypo + + "FXAssembly", + "ThisAssembly", + "AssemblyRef", + "SRETW", + "MatchState", + "__DynamicallyInvokableAttribute" + + // ReSharper restore StringLiteralTypo + }; + + private static readonly ConcurrentDictionary, Invocability> invocabilityMap = new ConcurrentDictionary, Invocability>(); + + private static readonly NumericTypes[] numericConversions = + { + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/numeric-conversions + + // IMPORTANT: maintain NumericType order + + /* None */ NumericTypes.None, + /* Char */ NumericTypes.UInt16 | NumericTypes.Int32 | NumericTypes.UInt32 | NumericTypes.Int64 | NumericTypes.UInt64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr | NumericTypes.UIntPtr, + /* SByte */ NumericTypes.Int16 | NumericTypes.Int32 | NumericTypes.Int64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr, + /* Byte */ NumericTypes.Int16 | NumericTypes.UInt16 | NumericTypes.Int32 | NumericTypes.UInt32 | NumericTypes.Int64 | NumericTypes.UInt64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr | NumericTypes.UIntPtr, + /* Int16 */ NumericTypes.Int32 | NumericTypes.Int64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr, + /* UInt16 */ NumericTypes.Int32 | NumericTypes.UInt32 | NumericTypes.Int64 | NumericTypes.UInt64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr | NumericTypes.UIntPtr, + /* Int32 */ NumericTypes.Int64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.IntPtr, + /* UInt32 */ NumericTypes.Int64 | NumericTypes.UInt64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal | NumericTypes.UIntPtr, + /* Int64 */ NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal, + /* UInt64 */ NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal, + /* IntPtr */ NumericTypes.Int64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal, + /* UIntPtr */ NumericTypes.UInt64 | NumericTypes.Single | NumericTypes.Double | NumericTypes.Decimal, + /* Single */ NumericTypes.Double, + /* Double */ NumericTypes.None, + /* Decimal */ NumericTypes.None + }; + + public static bool IsStatic(this Type type) + { + return type.IsAbstract && type.IsSealed; + } + + public static bool IsSpecific(this Type type) + { + return !type.IsGenericParameter && !type.ContainsGenericParameters; + } + + public static bool IsCompilerGenerated(this Type type, IHostContext context) + { + return type.HasCustomAttributes(context, false); + } + + public static bool IsFlagsEnum(this Type type, IHostContext context) + { + return type.IsEnum && type.HasCustomAttributes(context, false); + } + + public static bool IsImportable(this Type type, IHostContext context) + { + if (!type.IsNested && !type.IsSpecialName && !type.IsCompilerGenerated(context)) + { + var locator = type.GetLocator(); + return !importDenyList.Contains(locator) && IsValidLocator(locator); + } + + return false; + } + + public static bool IsAnonymous(this Type type, IHostContext context) + { + if (!type.IsGenericType) + { + return false; + } + + if ((type.Attributes & TypeAttributes.VisibilityMask) != TypeAttributes.NotPublic) + { + return false; + } + + var name = type.Name; + + if (!name.StartsWith("<>", StringComparison.Ordinal) && !name.StartsWith("VB$", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (!name.Contains("AnonymousType")) + { + return false; + } + + if (!type.IsCompilerGenerated(context)) + { + return false; + } + + return true; + } + + public static bool IsIntegral(this Type type) + { + return + (type == typeof(char)) || + (type == typeof(sbyte)) || + (type == typeof(byte)) || + (type == typeof(short)) || + (type == typeof(ushort)) || + (type == typeof(int)) || + (type == typeof(uint)) || + (type == typeof(long)) || + (type == typeof(ulong)) || + (type == typeof(IntPtr)) || + (type == typeof(UIntPtr)); + } + + public static bool IsFloatingPoint(this Type type) + { + return + (type == typeof(float)) || + (type == typeof(double)) || + (type == typeof(decimal)); + } + + public static bool IsNumeric(this Type type, out bool isIntegral) + { + return (isIntegral = type.IsIntegral()) || type.IsFloatingPoint(); + } + + public static bool IsNumeric(this Type type) + { + return type.IsNumeric(out _); + } + + public static bool IsNullable(this Type type) + { + return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>)); + } + + public static bool IsNullableNumeric(this Type type) + { + return + (type == typeof(char?)) || + (type == typeof(sbyte?)) || + (type == typeof(byte?)) || + (type == typeof(short?)) || + (type == typeof(ushort?)) || + (type == typeof(int?)) || + (type == typeof(uint?)) || + (type == typeof(long?)) || + (type == typeof(ulong?)) || + (type == typeof(IntPtr?)) || + (type == typeof(UIntPtr?)) || + (type == typeof(float?)) || + (type == typeof(double?)) || + (type == typeof(decimal?)); + } + + public static bool IsUnknownCOMObject(this Type type) + { + return type.IsCOMObject && (type.GetInterfaces().Length < 1); + } + + public static bool IsAssignableFromValue(this Type type, ref object value) + { + return type.IsAssignableFromValueInternal(ref value, null, null); + } + + public static bool IsAssignableToGenericType(this Type type, Type genericTypeDefinition, out Type[] typeArgs) + { + Debug.Assert(genericTypeDefinition.IsGenericTypeDefinition); + + for (var testType = type; testType != null; testType = testType.BaseType) + { + if (testType.IsGenericType && (testType.GetGenericTypeDefinition() == genericTypeDefinition)) + { + typeArgs = testType.GetGenericArguments(); + return true; + } + } + + var matches = type.GetInterfaces().Where(testType => testType.IsGenericType && (testType.GetGenericTypeDefinition() == genericTypeDefinition)).ToArray(); + if (matches.Length == 1) + { + typeArgs = matches[0].GetGenericArguments(); + return true; + } + + typeArgs = null; + return false; + } + + public static bool IsImplicitlyConvertibleFromValue(this Type type, Type sourceType, ref object value) + { + return IsImplicitlyConvertibleFromValueInternal(type, sourceType, type, ref value) || IsImplicitlyConvertibleFromValueInternal(sourceType, sourceType, type, ref value); + } + + public static bool IsNumericallyConvertibleFrom(this Type type, Type valueType) + { + return numericConversions[(int)valueType.GetNumericType()].HasFlag(GetNumericTypes(type.GetNumericType())); + } + + public static bool HasExtensionMethods(this Type type, IHostContext context) + { + return type.HasCustomAttributes(context, false); + } + + public static bool EqualsOrDeclares(this Type type, Type thatType) + { + for (; thatType != null; thatType = thatType.DeclaringType) + { + if (thatType == type) + { + return true; + } + } + + return false; + } + + public static bool IsFamilyOf(this Type type, Type thatType) + { + for (; type != null; type = type.DeclaringType) + { + if ((type == thatType) || type.IsSubclassOf(thatType)) + { + return true; + } + } + + return false; + } + + public static bool IsFriendOf(this Type type, IHostContext context, Type thatType) + { + return type.Assembly.IsFriendOf(context, thatType.Assembly); + } + + public static bool IsCOMVisible(this Type type, IHostContext context) + { + var attribute = type.GetOrLoadCustomAttribute(context, false); + if (attribute != null) + { + return attribute.Value; + } + + attribute = type.Assembly.GetOrLoadCustomAttribute(context, false); + if (attribute != null) + { + return attribute.Value; + } + + return false; + } + + public static string GetRootName(this Type type) + { + return StripGenericSuffix(type.Name); + } + + public static string GetFullRootName(this Type type) + { + return StripGenericSuffix(type.FullName); + } + + public static string GetFriendlyName(this Type type) + { + if (type.IsUnknownCOMObject()) + { + var clsid = type.GUID; + if (HResult.Succeeded(NativeMethods.ProgIDFromCLSID(ref clsid, out var progID))) + { + return progID; + } + } + + return type.GetFriendlyName(GetRootName); + } + + public static string GetFullFriendlyName(this Type type) + { + if (type.IsUnknownCOMObject()) + { + var clsid = type.GUID; + if (HResult.Succeeded(NativeMethods.ProgIDFromCLSID(ref clsid, out var progID))) + { + return progID; + } + } + + return type.GetFriendlyName(GetFullRootName); + } + + public static string GetLocator(this Type type) + { + Debug.Assert(!type.IsNested); + return type.GetFullRootName(); + } + + public static int GetGenericParamCount(this Type type) + { + return type.GetGenericArguments().Count(typeArg => typeArg.IsGenericParameter); + } + + public static IEnumerable GetScriptableEvents(this Type type, IHostContext context, BindingFlags bindFlags) + { + var events = type.GetEvents(bindFlags).AsEnumerable(); + if (type.IsInterface) + { + events = events.Concat(type.GetInterfaces().SelectMany(interfaceType => interfaceType.GetScriptableEvents(context, bindFlags))); + } + + return events.Where(eventInfo => eventInfo.IsScriptable(context)); + } + + public static EventInfo GetScriptableEvent(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + try + { + var eventInfo = type.GetScriptableEventInternal(context, name, bindFlags); + if (eventInfo != null) + { + return eventInfo; + } + } + catch (AmbiguousMatchException) + { + } + + return type.GetScriptableEvents(context, bindFlags).FirstOrDefault(eventInfo => string.Equals(eventInfo.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + + public static IEnumerable GetScriptableFields(this Type type, IHostContext context, BindingFlags bindFlags) + { + return type.GetFields(bindFlags).Where(field => field.IsScriptable(context)); + } + + public static FieldInfo GetScriptableField(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + var candidate = type.GetField(name, bindFlags); + if ((candidate != null) && candidate.IsScriptable(context) && string.Equals(candidate.GetScriptName(context), name, bindFlags.GetMemberNameComparison())) + { + return candidate; + } + + return type.GetScriptableFields(context, bindFlags).FirstOrDefault(field => string.Equals(field.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + + public static IEnumerable GetScriptableMethods(this Type type, IHostContext context, BindingFlags bindFlags) + { + var methods = type.GetMethods(bindFlags).AsEnumerable(); + if (type.IsInterface) + { + methods = methods.Concat(type.GetInterfaces().SelectMany(interfaceType => interfaceType.GetScriptableMethods(context, bindFlags))); + methods = methods.Concat(typeof(object).GetScriptableMethods(context, bindFlags)); + } + + return methods.Where(method => method.IsScriptable(context)); + } + + public static IEnumerable GetScriptableMethods(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + return type.GetScriptableMethods(context, bindFlags).Where(method => string.Equals(method.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + + public static IEnumerable GetScriptableProperties(this Type type, IHostContext context, BindingFlags bindFlags) + { + var properties = type.GetProperties(bindFlags).AsEnumerable(); + if (type.IsInterface) + { + properties = properties.Concat(type.GetInterfaces().SelectMany(interfaceType => interfaceType.GetScriptableProperties(context, bindFlags))); + } + + return properties.Where(property => property.IsScriptable(context)); + } + + public static IEnumerable GetScriptableDefaultProperties(this Type type, IHostContext context, BindingFlags bindFlags) + { + if (type.IsArray) + { + var property = typeof(IList<>).MakeSpecificType(type.GetElementType()).GetProperty("Item"); + return (property != null) ? property.ToEnumerable() : ArrayHelpers.GetEmptyArray(); + } + + var properties = type.GetProperties(bindFlags).AsEnumerable(); + if (type.IsInterface) + { + properties = properties.Concat(type.GetInterfaces().SelectMany(interfaceType => interfaceType.GetScriptableProperties(context, bindFlags))); + } + + var defaultMembers = type.GetDefaultMembers(); + return properties.Where(property => property.IsScriptable(context) && (defaultMembers.Contains(property) || property.IsDispID(context, SpecialDispIDs.Default))); + } + + public static IEnumerable GetScriptableProperties(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + return type.GetScriptableProperties(context, bindFlags).Where(property => string.Equals(property.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + + public static PropertyInfo GetScriptableProperty(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + var candidates = type.GetProperty(name, bindFlags)?.ToEnumerable() ?? Enumerable.Empty(); + if (type.IsInterface) + { + candidates = candidates.Concat(type.GetInterfaces().Select(interfaceType => interfaceType.GetScriptableProperty(context, name, bindFlags))); + } + + try + { + // ReSharper disable once RedundantEnumerableCastCall + return candidates.OfType().SingleOrDefault(property => (property.GetIndexParameters().Length < 1) && property.IsScriptable(context) && string.Equals(property.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + catch (InvalidOperationException exception) + { + throw new AmbiguousMatchException($"Multiple matches found for property name '{name}'", exception); + } + } + + public static PropertyInfo GetScriptableProperty(this Type type, IHostContext context, string name, BindingFlags bindFlags, object[] args, object[] bindArgs) + { + if (bindArgs.Length < 1) + { + try + { + var property = type.GetScriptableProperty(context, name, bindFlags); + if (property != null) + { + return property; + } + } + catch (AmbiguousMatchException) + { + } + } + + var candidates = type.GetScriptableProperties(context, name, bindFlags).Distinct(PropertySignatureComparer.Instance).ToArray(); + return BindToMember(context, candidates, bindFlags, args, bindArgs); + } + + public static PropertyInfo GetScriptableDefaultProperty(this Type type, IHostContext context, BindingFlags bindFlags, object[] args, object[] bindArgs) + { + var candidates = type.GetScriptableDefaultProperties(context, bindFlags).Distinct(PropertySignatureComparer.Instance).ToArray(); + return BindToMember(context, candidates, bindFlags, args, bindArgs); + } + + public static IEnumerable GetScriptableNestedTypes(this Type type, IHostContext context, BindingFlags bindFlags) + { + return type.GetNestedTypes(bindFlags).Where(nestedType => nestedType.IsScriptable(context)); + } + + public static Invocability GetInvocability(this Type type, IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + return invocabilityMap.GetOrAdd(Tuple.Create(type, bindFlags, context.AccessContext, context.DefaultAccess, ignoreDynamic), _ => GetInvocabilityInternal(type, context, bindFlags, ignoreDynamic)); + } + + public static object CreateInstance(this Type type, params object[] args) + { + return type.CreateInstance(BindingFlags.Public, args); + } + + public static object CreateInstance(this Type type, BindingFlags flags, params object[] args) + { + return type.InvokeMember(string.Empty, BindingFlags.CreateInstance | BindingFlags.Instance | (flags & ~BindingFlags.Static), null, null, args, CultureInfo.InvariantCulture); + } + + public static object CreateInstance(this Type type, IHostContext context, HostTarget target, object[] args, object[] bindArgs) + { + if (type.IsCOMObject) + { + return type.CreateInstance(args); + } + + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + var signature = new BindSignature(context.AccessContext, flags, target, type.TypeHandle.Value.ToString(), ArrayHelpers.GetEmptyArray(), bindArgs); + if (context.Engine.TryGetCachedConstructorBindResult(signature, out var boundConstructor)) + { + return InvokeHelpers.InvokeConstructor(context, boundConstructor, args); + } + + var constructors = type.GetConstructors(flags); + if (type.IsValueType && (args.Length < 1) && !constructors.Any(testConstructor => testConstructor.GetParameters().Length < 1)) + { + return type.CreateInstance(); + } + + var candidates = constructors.Where(testConstructor => testConstructor.IsAccessible(context) && !testConstructor.IsBlockedFromScript(context, context.DefaultAccess)).ToArray(); + if (candidates.Length < 1) + { + throw new MissingMethodException(MiscHelpers.FormatInvariant("Type '{0}' has no constructor that matches the specified arguments", type.GetFullFriendlyName())); + } + + var constructor = BindToMember(context, candidates, flags, args, bindArgs); + if (constructor == null) + { + throw new MissingMethodException(MiscHelpers.FormatInvariant("Type '{0}' has no constructor that matches the specified arguments", type.GetFullFriendlyName())); + } + + context.Engine.CacheConstructorBindResult(signature, constructor); + return InvokeHelpers.InvokeConstructor(context, constructor, args); + } + + public static Type MakeSpecificType(this Type template, params Type[] typeArgs) + { + Debug.Assert(template.GetGenericParamCount() <= typeArgs.Length); + return template.ApplyTypeArguments(typeArgs); + } + + public static Type ApplyTypeArguments(this Type type, params Type[] typeArgs) + { + if (!type.IsSpecific()) + { + Debug.Assert(typeArgs.All(typeArg => typeArg.IsSpecific())); + + var finalTypeArgs = (Type[])type.GetGenericArguments().Clone(); + for (int finalIndex = 0, index = 0; finalIndex < finalTypeArgs.Length; finalIndex++) + { + if (finalTypeArgs[finalIndex].IsGenericParameter) + { + finalTypeArgs[finalIndex] = typeArgs[index++]; + if (index >= typeArgs.Length) + { + break; + } + } + } + + return type.GetGenericTypeDefinition().MakeGenericType(finalTypeArgs); + } + + return type; + } + + public static T BindToMember(IHostContext context, T[] candidates, BindingFlags bindFlags, object[] args, object[] bindArgs) where T : MethodBase + { + T result = null; + + if (candidates.Length > 0) + { + var bindCandidates = GetBindCandidates(context, candidates, args, bindArgs.Select(GetBindArgType).ToArray()).ToArray(); + result = SelectBindCandidate(bindCandidates); + } + + return result; + } + + public static PropertyInfo BindToMember(IHostContext context, PropertyInfo[] candidates, BindingFlags bindFlags, object[] args, object[] bindArgs) + { + PropertyInfo result = null; + + if (candidates.Length > 0) + { + var bindCandidates = GetBindCandidates(context, candidates, args, bindArgs.Select(GetBindArgType).ToArray()).ToArray(); + result = SelectBindCandidate(bindCandidates); + + if (result == null) + { + // the default binder fails to bind to some COM properties because of by-ref parameter types + if (candidates.Length == 1) + { + var parameters = candidates[0].GetIndexParameters(); + if ((bindArgs.Length == parameters.Length) || ((bindArgs.Length > 0) && (parameters.Length >= bindArgs.Length))) + { + result = candidates[0]; + } + } + } + } + + return result; + } + + public static HostType ImportType(string typeName, string assemblyName, bool useAssemblyName, object[] hostTypeArgs) + { + if (!IsValidLocator(typeName)) + { + throw new ArgumentException("Invalid type name", nameof(typeName)); + } + + if (useAssemblyName && string.IsNullOrWhiteSpace(assemblyName)) + { + throw new ArgumentException("Invalid assembly name", nameof(assemblyName)); + } + + if (!hostTypeArgs.All(arg => arg is HostType)) + { + throw new ArgumentException("Invalid generic type argument"); + } + + var typeArgs = hostTypeArgs.Cast().Select(hostType => hostType.GetTypeArg()).ToArray(); + return ImportType(typeName, assemblyName, useAssemblyName, typeArgs); + } + + public static HostType ImportType(string typeName, string assemblyName, bool useAssemblyName, Type[] typeArgs) + { + const int maxTypeArgCount = 16; + + if ((typeArgs != null) && (typeArgs.Length > 0)) + { + var template = ImportType(typeName, assemblyName, useAssemblyName, typeArgs.Length); + if (template == null) + { + throw new TypeLoadException(MiscHelpers.FormatInvariant("Could not find a matching generic type definition for '{0}'", typeName)); + } + + return HostType.Wrap(template.MakeSpecificType(typeArgs)); + } + + var type = ImportType(typeName, assemblyName, useAssemblyName, 0); + + // ReSharper disable RedundantEnumerableCastCall + + // the OfType() call is not redundant; it filters out null elements + var counts = Enumerable.Range(1, maxTypeArgCount); + var templates = counts.Select(count => ImportType(typeName, assemblyName, useAssemblyName, count)).OfType().ToArray(); + + // ReSharper restore RedundantEnumerableCastCall + + if (templates.Length < 1) + { + if (type == null) + { + throw new TypeLoadException(MiscHelpers.FormatInvariant("Could not find a specific type or generic type definition for '{0}'", typeName)); + } + + return HostType.Wrap(type); + } + + if (type == null) + { + return HostType.Wrap(templates); + } + + return HostType.Wrap(type.ToEnumerable().Concat(templates).ToArray()); + } + + private static Type ImportType(string typeName, string assemblyName, bool useAssemblyName, int typeArgCount) + { + var assemblyQualifiedName = GetFullTypeName(typeName, assemblyName, useAssemblyName, typeArgCount); + + Type type = null; + try + { + type = Type.GetType(assemblyQualifiedName); + } + catch (ArgumentException) + { + } + catch (TypeLoadException) + { + } + catch (FileLoadException) + { + } + + return ((type != null) && useAssemblyName && (type.AssemblyQualifiedName != assemblyQualifiedName)) ? null : type; + } + + private static string GetFriendlyName(this Type type, Func getBaseName) + { + Debug.Assert(type.IsSpecific()); + if (type.IsArray) + { + var commas = new string(Enumerable.Repeat(',', type.GetArrayRank() - 1).ToArray()); + return MiscHelpers.FormatInvariant("{0}[{1}]", type.GetElementType().GetFriendlyName(getBaseName), commas); + } + + var typeArgs = type.GetGenericArguments(); + var parentPrefix = string.Empty; + if (type.IsNested) + { + var parentType = type.DeclaringType.MakeSpecificType(typeArgs); + parentPrefix = parentType.GetFriendlyName(getBaseName) + "."; + typeArgs = typeArgs.Skip(parentType.GetGenericArguments().Length).ToArray(); + getBaseName = GetRootName; + } + + if (typeArgs.Length < 1) + { + return MiscHelpers.FormatInvariant("{0}{1}", parentPrefix, getBaseName(type)); + } + + var name = getBaseName(type.GetGenericTypeDefinition()); + var paramList = string.Join(",", typeArgs.Select(typeArg => typeArg.GetFriendlyName(getBaseName))); + return MiscHelpers.FormatInvariant("{0}{1}<{2}>", parentPrefix, name, paramList); + } + + private static EventInfo GetScriptableEventInternal(this Type type, IHostContext context, string name, BindingFlags bindFlags) + { + var candidates = type.GetEvent(name, bindFlags)?.ToEnumerable() ?? Enumerable.Empty(); + if (type.IsInterface) + { + candidates = candidates.Concat(type.GetInterfaces().Select(interfaceType => interfaceType.GetScriptableEventInternal(context, name, bindFlags))); + } + + try + { + // ReSharper disable once RedundantEnumerableCastCall + return candidates.OfType().SingleOrDefault(eventInfo => eventInfo.IsScriptable(context) && string.Equals(eventInfo.GetScriptName(context), name, bindFlags.GetMemberNameComparison())); + } + catch (InvalidOperationException exception) + { + throw new AmbiguousMatchException($"Multiple matches found for event name '{name}'", exception); + } + } + + private static Invocability GetInvocabilityInternal(Type type, IHostContext context, BindingFlags bindFlags, bool ignoreDynamic) + { + if (typeof(Delegate).IsAssignableFrom(type)) + { + return Invocability.Delegate; + } + + if (!ignoreDynamic && typeof(IDynamicMetaObjectProvider).IsAssignableFrom(type)) + { + return Invocability.Dynamic; + } + + if (type.GetScriptableDefaultProperties(context, bindFlags).Any()) + { + return Invocability.DefaultProperty; + } + + return Invocability.None; + } + + private static bool IsValidLocator(string name) + { + return !string.IsNullOrWhiteSpace(name) && name.All(IsValidLocatorChar); + } + + private static bool IsValidLocatorChar(char ch) + { + return char.IsLetterOrDigit(ch) || (ch == '_') || (ch == '.'); + } + + private static string StripGenericSuffix(string name) + { + Debug.Assert(!string.IsNullOrWhiteSpace(name)); + var index = name.LastIndexOf('`'); + return (index >= 0) ? name.Substring(0, index) : name; + } + + private static bool IsBindableFromArg(this Type type, object value, Type valueType, out BindArgCost cost) + { + cost = new BindArgCost(); + return type.IsAssignableFromValueInternal(ref value, valueType, cost); + } + + private static bool IsAssignableFromValueInternal(this Type type, ref object value, Type valueType, BindArgCost cost) + { + var typeIsByRef = type.IsByRef; + if (typeIsByRef) + { + type = type.GetElementType(); + } + + var valueIsByRef = (valueType != null) && valueType.IsByRef; + if (valueIsByRef) + { + valueType = valueType.GetElementType(); + } + + if ((cost != null) && (typeIsByRef != valueIsByRef)) + { + cost.Flags |= BindArgFlags.ByRefMismatch; + } + + if ((value == null) && (valueType == null)) + { + if (type.IsNullable()) + { + if (cost != null) + { + cost.NumericType = Nullable.GetUnderlyingType(type).GetNumericType(); + } + + return true; + } + + return !type.IsValueType; + } + + if (valueType == null) + { + valueType = value.GetType(); + } + + if (valueType == type) + { + return true; + } + + if (type.IsAssignableFrom(valueType)) + { + if (cost != null) + { + if (type.IsNullable()) + { + cost.Flags |= BindArgFlags.NullableTransition; + cost.NumericType = Nullable.GetUnderlyingType(type).GetNumericType(); + } + else if (TypeNode.TryGetUpcastCount(valueType, type, out var count)) + { + cost.UpcastCount = count; + } + } + + return true; + } + + if (type.IsImplicitlyConvertibleFromValue(valueType, ref value)) + { + if (cost != null) + { + cost.Flags |= BindArgFlags.ImplicitConversion; + } + + return true; + } + + if (value == null) + { + return false; + } + + if (type.IsNullable()) + { + var underlyingType = Nullable.GetUnderlyingType(type); + if (underlyingType.IsAssignableFromValueInternal(ref value, valueType, cost)) + { + if (cost != null) + { + cost.Flags |= BindArgFlags.NullableTransition; + cost.NumericType = underlyingType.GetNumericType(); + } + + return true; + } + + return false; + } + + if (!type.IsValueType) + { + if (type.IsInterface && type.IsImport && valueType.IsCOMObject) + { + var result = false; + var pUnknown = Marshal.GetIUnknownForObject(value); + + var iid = type.GUID; + if (iid != Guid.Empty) + { + if (HResult.Succeeded(Marshal.QueryInterface(pUnknown, ref iid, out var pInterface))) + { + Marshal.Release(pInterface); + result = true; + } + } + + Marshal.Release(pUnknown); + return result; + } + + return false; + } + + if (!valueType.IsValueType) + { + return false; + } + + if (type.IsEnum) + { + return Enum.GetUnderlyingType(type).IsAssignableFromValueInternal(ref value, valueType, cost) && value.IsZero(); + } + + if (valueType.IsEnum) + { + return false; + } + + if (type.IsNumeric(out var typeIsIntegral)) + { + if (typeIsIntegral) + { + if (!valueType.IsIntegral() && !value.IsWholeNumber()) + { + return false; + } + } + else + { + if (!valueType.IsNumeric(out var valueTypeIsIntegral)) + { + return false; + } + + // special case for method binding only + + if ((cost != null) && !valueTypeIsIntegral && !type.IsNumericallyConvertibleFrom(valueType)) + { + return false; + } + } + + var tempValue = value; + if (MiscHelpers.Try(out var tempResult, () => Convert.ChangeType(tempValue, type))) + { + if (cost != null) + { + cost.Flags |= BindArgFlags.NumericConversion; + cost.NumericType = type.GetNumericType(); + } + + value = tempResult; + return true; + } + } + + return false; + } + + private static bool IsImplicitlyConvertibleFromValueInternal(Type definingType, Type sourceType, Type targetType, ref object value) + { + foreach (var converter in definingType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(method => method.Name == "op_Implicit")) + { + var parameters = converter.GetParameters(); + if ((parameters.Length == 1) && parameters[0].ParameterType.IsAssignableFrom(sourceType) && targetType.IsAssignableFrom(converter.ReturnType)) + { + var args = new[] { value }; + if (MiscHelpers.Try(out var result, () => converter.Invoke(null, args))) + { + value = result; + return true; + } + } + } + + return false; + } + + private static NumericType GetNumericType(this Type type) + { + if (type == typeof(char)) return NumericType.Char; + if (type == typeof(sbyte)) return NumericType.SByte; + if (type == typeof(byte)) return NumericType.Byte; + if (type == typeof(short)) return NumericType.Int16; + if (type == typeof(ushort)) return NumericType.UInt16; + if (type == typeof(int)) return NumericType.Int32; + if (type == typeof(uint)) return NumericType.UInt32; + if (type == typeof(long)) return NumericType.Int64; + if (type == typeof(ulong)) return NumericType.UInt64; + if (type == typeof(IntPtr)) return NumericType.IntPtr; + if (type == typeof(UIntPtr)) return NumericType.UIntPtr; + if (type == typeof(float)) return NumericType.Single; + if (type == typeof(double)) return NumericType.Double; + if (type == typeof(decimal)) return NumericType.Decimal; + return NumericType.None; + } + + private static NumericTypes GetNumericTypes(NumericType numericType) + { + return (numericType == NumericType.None) ? NumericTypes.None : (NumericTypes)(1 << (int)numericType); + } + + private static Type GetBindArgType(object bindArg) + { + if (bindArg is HostTarget hostTarget) + { + return hostTarget.Type; + } + + if (bindArg != null) + { + return bindArg.GetType(); + } + + return null; + } + + private static IEnumerable> GetBindCandidates(IHostContext context, T[] candidates, object[] args, Type[] argTypes) where T : MethodBase + { + return GetBindCandidates(context, candidates, candidate => candidate.GetParameters(), args, argTypes); + } + + private static IEnumerable> GetBindCandidates(IHostContext context, PropertyInfo[] candidates, object[] args, Type[] argTypes) + { + return GetBindCandidates(context, candidates, candidate => candidate.GetIndexParameters(), args, argTypes); + } + + private static IEnumerable> GetBindCandidates(IHostContext context, T[] candidates, Func getParameters, object[] args, Type[] argTypes) where T : MemberInfo + { + foreach (var candidate in candidates) + { + if (MiscHelpers.Try(out var bindCandidate, () => BindCandidate.TryCreateInstance(context, candidate, getParameters(candidate), args, argTypes)) && (bindCandidate != null)) + { + yield return bindCandidate; + } + } + } + + private static T SelectBindCandidate(BindCandidate[] bindCandidates) where T : MemberInfo + { + if (bindCandidates.Length < 1) + { + return null; + } + + if (bindCandidates.Length < 2) + { + return bindCandidates[0].Candidate; + } + + Array.Sort(bindCandidates, Comparer>.Default); + + if (bindCandidates[0].CompareTo(bindCandidates[1]) == 0) + { + throw new AmbiguousMatchException("Ambiguous match found for the specified arguments"); + } + + return bindCandidates[0].Candidate; + } + + #region Nested type: NumericType + + private enum NumericType + { + // IMPORTANT: maintain order and numeric mapping + + None, + Char, + SByte, + Byte, + Int16, + UInt16, + Int32, + UInt32, + Int64, + UInt64, + IntPtr, + UIntPtr, + Single, + Double, + Decimal + } + + #endregion + + #region Nested type: NumericTypes + + [Flags] + private enum NumericTypes + { + // ReSharper disable UnusedMember.Local + + None = 0, + Char = 1 << NumericType.Char, + SByte = 1 << NumericType.SByte, + Byte = 1 << NumericType.Byte, + Int16 = 1 << NumericType.Int16, + UInt16 = 1 << NumericType.UInt16, + Int32 = 1 << NumericType.Int32, + UInt32 = 1 << NumericType.UInt32, + Int64 = 1 << NumericType.Int64, + UInt64 = 1 << NumericType.UInt64, + IntPtr = 1 << NumericType.IntPtr, + UIntPtr = 1 << NumericType.UIntPtr, + Single = 1 << NumericType.Single, + Double = 1 << NumericType.Double, + Decimal = 1 << NumericType.Decimal + + // ReSharper restore UnusedMember.Local + } + + #endregion + + #region Nested type: TypeNode + + private sealed class TypeNode + { + private static readonly ConcurrentDictionary typeNodeMap = new ConcurrentDictionary(); + + private readonly Type type; + + private readonly TypeNode baseNode; + + private readonly IReadOnlyCollection interfaceNodes; + + public static bool TryGetUpcastCount(Type sourceType, Type targetType, out uint count) + { + count = uint.MaxValue; + + if (targetType != typeof(object)) + { + GetOrCreate(sourceType).GetUpcastCountInternal(targetType, 0U, ref count); + return count < uint.MaxValue; + } + + return true; + } + + private TypeNode(Type type, TypeNode baseNode, IReadOnlyCollection interfaceNodes) + { + this.type = type; + this.baseNode = baseNode; + this.interfaceNodes = interfaceNodes; + } + + private static TypeNode GetOrCreate(Type type) => typeNodeMap.GetOrAdd(type, Create); + + private static TypeNode Create(Type type) + { + TypeNode baseNode = null; + var redundantInterfaces = new List(); + + var baseType = type.BaseType; + if (baseType != null) + { + redundantInterfaces.AddRange(baseType.GetInterfaces()); + baseNode = GetOrCreate(baseType); + } + + var allInterfaces = type.GetInterfaces(); + foreach (var interfaceType in allInterfaces) + { + redundantInterfaces.AddRange(interfaceType.GetInterfaces()); + } + + var interfaces = allInterfaces.Except(redundantInterfaces.Distinct()); + return new TypeNode(type, baseNode, interfaces.Select(GetOrCreate).ToArray()); + } + + private void GetUpcastCountInternal(Type targetType, uint count, ref uint lowestCount) + { + if (type == targetType) + { + if (count < lowestCount) + { + lowestCount = count; + } + } + else + { + baseNode?.GetUpcastCountInternal(targetType, count + 1, ref lowestCount); + if (targetType.IsInterface) + { + foreach (var interfaceNode in interfaceNodes) + { + interfaceNode.GetUpcastCountInternal(targetType, count + 1, ref lowestCount); + } + } + } + } + } + + #endregion + + #region Nested type: PropertySignatureComparer + + private sealed class PropertySignatureComparer : EqualityComparer + { + public static readonly PropertySignatureComparer Instance = new PropertySignatureComparer(); + + public override bool Equals(PropertyInfo first, PropertyInfo second) + { + var firstParamTypes = first.GetIndexParameters().Select(param => param.ParameterType); + var secondParamTypes = second.GetIndexParameters().Select(param => param.ParameterType); + return firstParamTypes.SequenceEqual(secondParamTypes); + } + + public override int GetHashCode(PropertyInfo property) + { + var hashCode = 0; + + var parameters = property.GetIndexParameters(); + foreach (var param in parameters) + { + hashCode = unchecked((hashCode * 31) + param.ParameterType.GetHashCode()); + } + + return hashCode; + } + } + + #endregion + + #region Nested Type: BindArgFlag + + private enum BindArgFlag + { + // IMPORTANT: ascending cost order + + IsParamArrayArg, + NullableTransition, + NumericConversion, + ImplicitConversion, + ByRefMismatch + } + + #endregion + + #region Nested type: BindArgFlags + + [Flags] + private enum BindArgFlags : uint + { + IsParamArrayArg = 1 << BindArgFlag.IsParamArrayArg, + NullableTransition = 1 << BindArgFlag.NullableTransition, + NumericConversion = 1 << BindArgFlag.NumericConversion, + ImplicitConversion = 1 << BindArgFlag.ImplicitConversion, + ByRefMismatch = 1 << BindArgFlag.ByRefMismatch + } + + #endregion + + #region Nested type: BindArgCost + + private sealed class BindArgCost : IComparable + { + public BindArgFlags Flags; + public NumericType NumericType; + public uint UpcastCount; + + public int CompareTo(BindArgCost other) + { + var result = Flags.CompareTo(other.Flags); + if (result != 0) + { + return result; + } + + if ((NumericType != NumericType.None) && (other.NumericType != NumericType.None)) + { + result = NumericType.CompareTo(other.NumericType); + if (result != 0) + { + return result; + } + } + + return UpcastCount.CompareTo(other.UpcastCount); + } + } + + #endregion + + #region Nested type: BindCandidate + + private sealed class BindCandidate : IComparable> where T : MemberInfo + { + private readonly int defaultArgCount; + private readonly bool paramArray; + private readonly List argCosts; + + public T Candidate { get; } + + private BindCandidate(T candidate, int defaultArgCount, bool paramArray, List argCosts) + { + Candidate = candidate; + this.defaultArgCount = defaultArgCount; + this.paramArray = paramArray; + this.argCosts = argCosts; + } + + public int CompareTo(BindCandidate other) + { + Debug.Assert(argCosts.Count == other.argCosts.Count); + int result; + + for (var index = 0; index < argCosts.Count; index++) + { + result = argCosts[index].CompareTo(other.argCosts[index]); + if (result != 0) + { + return result; + } + } + + result = defaultArgCount.CompareTo(other.defaultArgCount); + if (result != 0) + { + return result; + } + + result = paramArray.CompareTo(other.paramArray); + if (result != 0) + { + return result; + } + + var declType = Candidate.DeclaringType; + var otherDeclType = other.Candidate.DeclaringType; + + if (otherDeclType == declType) + { + return 0; + } + + return TypeNode.TryGetUpcastCount(Candidate.DeclaringType, other.Candidate.DeclaringType, out _) ? -1 : 1; + } + + public static BindCandidate TryCreateInstance(IHostContext context, T candidate, ParameterInfo[] parameters, object[] args, Type[] argTypes) + { + var defaultArgCount = 0; + var paramArray = false; + var argCosts = new List(); + + var paramIndex = 0; + var argIndex = 0; + + Type paramType = null; + BindArgCost cost; + + for (; paramIndex < parameters.Length; paramIndex++) + { + var param = parameters[paramIndex]; + paramType = param.ParameterType; + + if ((paramIndex == (parameters.Length - 1)) && paramType.IsArray && CustomAttributes.Has(context, param, false)) + { + paramArray = true; + break; + } + + if (argIndex >= args.Length) + { + if (!param.IsOptional && !param.HasDefaultValue) + { + return null; + } + + defaultArgCount += 1; + continue; + } + + if (!paramType.IsBindableFromArg(args[argIndex], argTypes[argIndex], out cost)) + { + return null; + } + + argCosts.Add(cost); + ++argIndex; + } + + if (paramArray) + { + if (argIndex >= args.Length) + { + return new BindCandidate(candidate, defaultArgCount, true, argCosts); + } + + if ((argIndex == (args.Length - 1)) && paramType.IsBindableFromArg(args[argIndex], argTypes[argIndex], out cost)) + { + argCosts.Add(cost); + return new BindCandidate(candidate, defaultArgCount, true, argCosts); + } + + paramType = paramType.GetElementType(); + for (; argIndex < args.Length; argIndex++) + { + if (!paramType.IsBindableFromArg(args[argIndex], argTypes[argIndex], out cost)) + { + return null; + } + + cost.Flags |= BindArgFlags.IsParamArrayArg; + argCosts.Add(cost); + } + } + else if (argIndex < args.Length) + { + return null; + } + + return new BindCandidate(candidate, defaultArgCount, paramArray, argCosts); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/TypeHelpers.cs.meta b/Unity/Package/Runtime/Util/TypeHelpers.cs.meta new file mode 100644 index 000000000..4e5696356 --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 329f2aa4b34bfed4dab8013b57758f41 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/TypeTags.cs b/Unity/Package/Runtime/Util/TypeTags.cs new file mode 100644 index 000000000..d4e5b281c --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeTags.cs @@ -0,0 +1,18 @@ +namespace Microsoft.ClearScript.Util +{ + internal interface INothingTag + { + } + + internal interface IWindowsScriptEngineTag + { + } + + internal interface IVBScriptEngineTag + { + } + + internal interface IWindowsScriptItemTag + { + } +} diff --git a/Unity/Package/Runtime/Util/TypeTags.cs.meta b/Unity/Package/Runtime/Util/TypeTags.cs.meta new file mode 100644 index 000000000..1a70fee0c --- /dev/null +++ b/Unity/Package/Runtime/Util/TypeTags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8124202c31d08aa44958c5b5f552dc68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/UniqueNameManager.cs b/Unity/Package/Runtime/Util/UniqueNameManager.cs new file mode 100644 index 000000000..b95bdbcb1 --- /dev/null +++ b/Unity/Package/Runtime/Util/UniqueNameManager.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.ClearScript.Util +{ + internal interface IUniqueNameManager + { + string GetUniqueName(string inputName, string alternate); + } + + internal sealed class UniqueNameManager : IUniqueNameManager + { + private readonly Dictionary map = new Dictionary(); + + #region IUniqueNameManager implementation + + public string GetUniqueName(string inputName, string alternate) + { + lock (map) + { + var nonBlankName = MiscHelpers.EnsureNonBlank(inputName, alternate); + + map.TryGetValue(nonBlankName, out var count); + + map[nonBlankName] = ++count; + return (count < 2) ? nonBlankName : string.Concat(nonBlankName, " [", count, "]"); + } + } + + #endregion + } + + internal sealed class UniqueFileNameManager : IUniqueNameManager + { + private readonly Dictionary map = new Dictionary(); + + #region IUniqueNameManager implementation + + public string GetUniqueName(string inputName, string alternate) + { + lock (map) + { + var nonBlankName = MiscHelpers.EnsureNonBlank(Path.GetFileNameWithoutExtension(inputName), alternate); + var extension = Path.GetExtension(inputName); + + map.TryGetValue(nonBlankName, out var count); + + map[nonBlankName] = ++count; + return (count < 2) ? string.Concat(nonBlankName, extension) : string.Concat(nonBlankName, " [", count, "]", extension); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/UniqueNameManager.cs.meta b/Unity/Package/Runtime/Util/UniqueNameManager.cs.meta new file mode 100644 index 000000000..7a958ab67 --- /dev/null +++ b/Unity/Package/Runtime/Util/UniqueNameManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8830dae414ff4c43a5c436f26702c3f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs b/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs new file mode 100644 index 000000000..50c86e1e0 --- /dev/null +++ b/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs @@ -0,0 +1,819 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util +{ + internal static class UnmanagedMemoryHelpers + { + private delegate ulong ReadArrayFromUnmanagedMemoryHandler(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex); + private delegate ulong WriteArrayToUnmanagedMemoryHandler(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination); + + private static readonly Dictionary readArrayFromUnmanagedMemoryHandlerMap = new Dictionary + { + { typeof(byte), ReadByteArrayFromUnmanagedMemory }, + { typeof(sbyte), ReadSByteArrayFromUnmanagedMemory }, + { typeof(ushort), ReadUInt16ArrayFromUnmanagedMemory }, + { typeof(char), ReadCharArrayFromUnmanagedMemory }, // blittable because ClearScriptV8's StdChar is char16_t + { typeof(short), ReadInt16ArrayFromUnmanagedMemory }, + { typeof(uint), ReadUInt32ArrayFromUnmanagedMemory }, + { typeof(int), ReadInt32ArrayFromUnmanagedMemory }, + { typeof(long), ReadInt64ArrayFromUnmanagedMemory }, + { typeof(ulong), ReadUInt64ArrayFromUnmanagedMemory }, + { typeof(IntPtr), ReadIntPtrArrayFromUnmanagedMemory }, + { typeof(UIntPtr), ReadUIntPtrArrayFromUnmanagedMemory }, + { typeof(float), ReadSingleArrayFromUnmanagedMemory }, + { typeof(double), ReadDoubleArrayFromUnmanagedMemory } + }; + + private static readonly Dictionary writeArrayToUnmanagedMemoryHandlerMap = new Dictionary + { + { typeof(byte), WriteByteArrayToUnmanagedMemory }, + { typeof(sbyte), WriteSByteArrayToUnmanagedMemory }, + { typeof(ushort), WriteUInt16ArrayToUnmanagedMemory }, + { typeof(char), WriteCharArrayToUnmanagedMemory }, // blittable because ClearScriptV8's StdChar is char16_t + { typeof(short), WriteInt16ArrayToUnmanagedMemory }, + { typeof(uint), WriteUInt32ArrayToUnmanagedMemory }, + { typeof(int), WriteInt32ArrayToUnmanagedMemory }, + { typeof(long), WriteInt64ArrayToUnmanagedMemory }, + { typeof(ulong), WriteUInt64ArrayToUnmanagedMemory }, + { typeof(IntPtr), WriteIntPtrArrayToUnmanagedMemory }, + { typeof(UIntPtr), WriteUIntPtrArrayToUnmanagedMemory }, + { typeof(float), WriteSingleArrayToUnmanagedMemory }, + { typeof(double), WriteDoubleArrayToUnmanagedMemory } + }; + + public static ulong Copy(IntPtr pSource, ulong length, T[] destination, ulong destinationIndex) + { + return Copy(typeof(T), pSource, length, destination, destinationIndex); + } + + public static ulong Copy(T[] source, ulong sourceIndex, ulong length, IntPtr pDestination) + { + return Copy(typeof(T), source, sourceIndex, length, pDestination); + } + + private static ulong Copy(Type type, IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + if (readArrayFromUnmanagedMemoryHandlerMap.TryGetValue(type, out var handler)) + { + return handler(pSource, length, destinationArray, destinationIndex); + } + + throw new NotSupportedException("Unsupported unmanaged data transfer operation"); + } + + private static ulong Copy(Type type, Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + if (writeArrayToUnmanagedMemoryHandlerMap.TryGetValue(type, out var handler)) + { + return handler(sourceArray, sourceIndex, length, pDestination); + } + + throw new NotSupportedException("Unsupported unmanaged data transfer operation"); + } + + private static unsafe ulong ReadByteArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (byte[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (byte* pDest = destination) + { + var pSrc = (byte*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadSByteArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (sbyte[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + fixed (sbyte* pDest = destination) + { + var pSrc = (sbyte*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + + return length; + } + + private static unsafe ulong ReadUInt16ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (ushort[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + fixed (ushort* pDest = destination) + { + var pSrc = (ushort*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + + return length; + } + + private static unsafe ulong ReadCharArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (char[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (char* pDest = destination) + { + var pSrc = (char*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadInt16ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (short[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (short* pDest = destination) + { + var pSrc = (short*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadUInt32ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (uint[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + fixed (uint* pDest = destination) + { + var pSrc = (uint*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + + return length; + } + + private static unsafe ulong ReadInt32ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (int[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (int* pDest = destination) + { + var pSrc = (int*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadUInt64ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (ulong[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + fixed (ulong* pDest = destination) + { + var pSrc = (ulong*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + + return length; + } + + private static unsafe ulong ReadInt64ArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (long[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (long* pDest = destination) + { + var pSrc = (long*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadUIntPtrArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (UIntPtr[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + fixed (UIntPtr* pDest = destination) + { + var pSrc = (UIntPtr*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + + return length; + } + + private static unsafe ulong ReadIntPtrArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (IntPtr[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (IntPtr* pDest = destination) + { + var pSrc = (IntPtr*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadSingleArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (float[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (float* pDest = destination) + { + var pSrc = (float*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong ReadDoubleArrayFromUnmanagedMemory(IntPtr pSource, ulong length, Array destinationArray, ulong destinationIndex) + { + var destinationLength = (ulong)destinationArray.LongLength; + if (destinationIndex >= destinationLength) + { + throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + } + + var destination = (double[])destinationArray; + length = Math.Min(length, destinationLength - destinationIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(pSource, destination, Convert.ToInt32(destinationIndex), Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (double* pDest = destination) + { + var pSrc = (double*)pSource; + for (var index = 0UL; index < length; index++) + { + pDest[destinationIndex + index] = pSrc[index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteByteArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (byte[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (byte* pSrc = source) + { + var pDest = (byte*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteSByteArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (sbyte[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + fixed (sbyte* pSrc = source) + { + var pDest = (sbyte*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + + return length; + } + + private static unsafe ulong WriteUInt16ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (ushort[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + fixed (ushort* pSrc = source) + { + var pDest = (ushort*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + + return length; + } + + private static unsafe ulong WriteCharArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (char[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (char* pSrc = source) + { + var pDest = (char*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteInt16ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (short[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (short* pSrc = source) + { + var pDest = (short*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteUInt32ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (uint[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + fixed (uint* pSrc = source) + { + var pDest = (uint*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + + return length; + } + + private static unsafe ulong WriteInt32ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (int[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (int* pSrc = source) + { + var pDest = (int*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteUInt64ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (ulong[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + fixed (ulong* pSrc = source) + { + var pDest = (ulong*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + + return length; + } + + private static unsafe ulong WriteInt64ArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (long[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (long* pSrc = source) + { + var pDest = (long*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteUIntPtrArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (UIntPtr[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + fixed (UIntPtr* pSrc = source) + { + var pDest = (UIntPtr*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + + return length; + } + + private static unsafe ulong WriteIntPtrArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (IntPtr[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (IntPtr* pSrc = source) + { + var pDest = (IntPtr*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteSingleArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (float[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (float* pSrc = source) + { + var pDest = (float*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + private static unsafe ulong WriteDoubleArrayToUnmanagedMemory(Array sourceArray, ulong sourceIndex, ulong length, IntPtr pDestination) + { + var sourceLength = (ulong)sourceArray.LongLength; + if (sourceIndex >= sourceLength) + { + throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + } + + var source = (double[])sourceArray; + length = Math.Min(length, sourceLength - sourceIndex); + + try + { + VerifyMarshalCopyEnabled(); + Marshal.Copy(source, Convert.ToInt32(sourceIndex), pDestination, Convert.ToInt32(length)); + } + catch (OverflowException) + { + fixed (double* pSrc = source) + { + var pDest = (double*)pDestination; + for (var index = 0UL; index < length; index++) + { + pDest[index] = pSrc[sourceIndex + index]; + } + } + } + + return length; + } + + #region unit test support + + internal static bool DisableMarshalCopy; + + private static void VerifyMarshalCopyEnabled() + { + if (DisableMarshalCopy) + { + throw new OverflowException(); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs.meta b/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs.meta new file mode 100644 index 000000000..4d03f2ccc --- /dev/null +++ b/Unity/Package/Runtime/Util/UnmanagedMemoryHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f0b737d8ed89244f899b984ea5aecb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/VTableHelpers.cs b/Unity/Package/Runtime/Util/VTableHelpers.cs new file mode 100644 index 000000000..2402589b5 --- /dev/null +++ b/Unity/Package/Runtime/Util/VTableHelpers.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util +{ + internal static class VTableHelpers + { + public static T GetMethodDelegate(IntPtr pInterface, int methodIndex) where T : class + { + var pMethod = GetMethodPtr(pInterface, methodIndex); + return Marshal.GetDelegateForFunctionPointer(pMethod, typeof(T)) as T; + } + + public static IntPtr GetMethodPtr(IntPtr pInterface, int methodIndex) + { + var pVTable = Marshal.ReadIntPtr(pInterface); + return Marshal.ReadIntPtr(pVTable + methodIndex * IntPtr.Size); + } + + public static IntPtr ReadMethodPtr(IntPtr pSlot) + { + return Marshal.ReadIntPtr(pSlot); + } + + public static T SetMethodDelegate(IntPtr pInterface, int methodIndex, T del) where T : class + { + var pMethod = Marshal.GetFunctionPointerForDelegate((Delegate)(object)del); + SetMethodPtr(pInterface, methodIndex, pMethod); + return del; + } + + public static IntPtr SetMethodPtr(IntPtr pInterface, int methodIndex, IntPtr pMethod) + { + var pVTable = Marshal.ReadIntPtr(pInterface); + WriteMethodPtr(pVTable + methodIndex * IntPtr.Size, pMethod); + return pMethod; + } + + public static bool WriteMethodPtr(IntPtr pSlot, IntPtr pMethod) + { + if (NativeMethods.VirtualProtect(pSlot, (UIntPtr)IntPtr.Size, 0x04 /*PAGE_READWRITE*/, out var oldProtect)) + { + Marshal.WriteIntPtr(pSlot, pMethod); + NativeMethods.VirtualProtect(pSlot, (UIntPtr)IntPtr.Size, oldProtect, out oldProtect); + return true; + } + + return false; + } + } +} diff --git a/Unity/Package/Runtime/Util/VTableHelpers.cs.meta b/Unity/Package/Runtime/Util/VTableHelpers.cs.meta new file mode 100644 index 000000000..b39b836c8 --- /dev/null +++ b/Unity/Package/Runtime/Util/VTableHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f018ded57527321459d3291437d6d83d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/VTablePatcher.cs b/Unity/Package/Runtime/Util/VTablePatcher.cs new file mode 100644 index 000000000..06f2554cd --- /dev/null +++ b/Unity/Package/Runtime/Util/VTablePatcher.cs @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.Util +{ + [SuppressMessage("ReSharper", "CommentTypo", Justification = "This class uses comments to show machine code disassembly.")] + internal abstract class VTablePatcher + { + private static readonly HashSet patchedVTables = new HashSet(); + private static IntPtr hHeap; + + public static VTablePatcher GetInstance() + { + return Environment.Is64BitProcess ? VTablePatcher64.Instance : VTablePatcher32.Instance; + } + + public static object PatchLock => patchedVTables; + + public abstract void PatchDispatchEx(IntPtr pDispatchEx); + + private static void ApplyVTablePatches(IntPtr pInterface, params VTablePatch[] patches) + { + lock (PatchLock) + { + var pVTable = Marshal.ReadIntPtr(pInterface); + if (!patchedVTables.Contains(pVTable)) + { + patchedVTables.Add(pVTable); + EnsureHeap(); + + foreach (var patch in patches) + { + var pSlot = pVTable + patch.SlotIndex * IntPtr.Size; + var pTarget = VTableHelpers.ReadMethodPtr(pSlot); + + var thunkSize = patch.ThunkBytes.Length; + var pThunk = NativeMethods.HeapAlloc(hHeap, 0, (UIntPtr)thunkSize); + if (pThunk != IntPtr.Zero) + { + for (var index = 0; index < thunkSize; index++) + { + Marshal.WriteByte(pThunk + index, patch.ThunkBytes[index]); + } + + Marshal.WriteIntPtr(pThunk + patch.TargetOffset, pTarget); + if (!VTableHelpers.WriteMethodPtr(pSlot, pThunk)) + { + NativeMethods.HeapFree(hHeap, 0, pThunk); + } + } + } + } + } + } + + private static void EnsureHeap() + { + if (hHeap == IntPtr.Zero) + { + hHeap = NativeMethods.HeapCreate(0x00040001 /*HEAP_CREATE_ENABLE_EXECUTE|HEAP_NO_SERIALIZE*/, UIntPtr.Zero, UIntPtr.Zero); + if (hHeap == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + } + + #region Nested type: VTablePatcher32 + + private sealed class VTablePatcher32 : VTablePatcher + { + public static readonly VTablePatcher Instance = new VTablePatcher32(); + + private VTablePatcher32() + { + } + + public override void PatchDispatchEx(IntPtr pDispatchEx) + { + // JScript in Standards Mode extends the IDispatchEx contract slightly in order to + // pass extra data to the host. This confuses the CLR's IDispatchEx implementation. + // The vtable patches below sanitize the arguments before passing them through. + + ApplyVTablePatches( + pDispatchEx, + new VTablePatch + { + SlotIndex = 7, // IDispatchEx::GetDispID() + ThunkBytes = new byte[] { //------------------------- + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x81, 0x65, 0x10, 0xFF, 0xFF, 0xFF, 0x0F, // and dword ptr [grfdex],0FFFFFFFh + 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target + 0x5D, // pop ebp + 0xFF, 0xE0 // jmp eax + }, + TargetOffset = 11 + }, + new VTablePatch + { + SlotIndex = 9, // IDispatchEx::DeleteMemberByName() + ThunkBytes = new byte[] { // --------------------------------- + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x8B, 0x45, 0x10, // mov eax,dword ptr [grfdex] + 0x25, 0xFF, 0xFF, 0xFF, 0x0F, // and eax,0FFFFFFFh + 0x89, 0x45, 0x10, // mov dword ptr [grfdex],eax + 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target + 0x5D, // pop ebp + 0xFF, 0xE0 // jmp eax + }, + TargetOffset = 15 + }, + new VTablePatch + { + SlotIndex = 13, // IDispatchEx::GetNextDispID() + ThunkBytes = new byte[] { // ---------------------------- + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x81, 0x65, 0x0C, 0xFF, 0xFF, 0xFF, 0x0F, // and dword ptr [grfdex],0FFFFFFFh + 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, // mov eax,0BAADF00Dh <- Target + 0x5D, // pop ebp + 0xFF, 0xE0 // jmp eax + }, + TargetOffset = 11 + } + ); + } + } + + #endregion + + #region Nested type: VTablePatcher64 + + private sealed class VTablePatcher64 : VTablePatcher + { + public static readonly VTablePatcher Instance = new VTablePatcher64(); + + private VTablePatcher64() + { + } + + public override void PatchDispatchEx(IntPtr pDispatchEx) + { + // JScript in Standards Mode extends the IDispatchEx contract slightly in order to + // pass extra data to the host. This confuses the CLR's IDispatchEx implementation. + // The vtable patches below sanitize the arguments before passing them through. + + ApplyVTablePatches( + pDispatchEx, + new VTablePatch + { + SlotIndex = 7, // IDispatchEx::GetDispID() + ThunkBytes = new byte[] { //------------------------- + 0x41, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, // and r8d,0FFFFFFFh + 0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target + 0x48, 0xFF, 0xE0 // jmp rax + }, + TargetOffset = 9 + }, + new VTablePatch { + SlotIndex = 9, // IDispatchEx::DeleteMemberByName() + ThunkBytes = new byte[] { // --------------------------------- + 0x41, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, // and r8d,0FFFFFFFh + 0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target + 0x48, 0xFF, 0xE0 // jmp rax + }, + TargetOffset = 9 + }, + new VTablePatch { + SlotIndex = 13, // IDispatchEx::GetNextDispID() + ThunkBytes = new byte[] { // ---------------------------- + 0x81, 0xE2, 0xFF, 0xFF, 0xFF, 0x0F, // and edx,0FFFFFFFh + 0x48, 0xB8, 0x0D, 0xF0, 0xAD, 0xBA, 0x0D, 0xF0, 0xAD, 0xBA, // mov rax,0BAADF00DBAADF00Dh <- Target + 0x48, 0xFF, 0xE0 // jmp rax + }, + TargetOffset = 8 + } + ); + } + } + + #endregion + + #region Nested type: VTablePatch + + private sealed class VTablePatch + { + public int SlotIndex; + public byte[] ThunkBytes; + public int TargetOffset; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/VTablePatcher.cs.meta b/Unity/Package/Runtime/Util/VTablePatcher.cs.meta new file mode 100644 index 000000000..dd9abf05d --- /dev/null +++ b/Unity/Package/Runtime/Util/VTablePatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e10ddd205734ba41a1b51c35bfa6043 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Web.meta b/Unity/Package/Runtime/Util/Web.meta new file mode 100644 index 000000000..797941d0d --- /dev/null +++ b/Unity/Package/Runtime/Util/Web.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00cad2a1a43c1dd4280326c9645d4c1f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Web/WebContext.cs b/Unity/Package/Runtime/Util/Web/WebContext.cs new file mode 100644 index 000000000..6d26d5c0e --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebContext.cs @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.Util.Web +{ + internal sealed class WebContext + { + public WebRequest Request { get; } + + public WebResponse Response { get; } + + private WebContext(Socket socket, Uri uri, NameValueCollection headers) + { + Request = new WebRequest(uri, headers); + Response = new WebResponse(socket, 200); + } + + public static async Task CreateAsync(Socket socket) + { + try + { + var lines = new List(); + + while (true) + { + var line = await socket.ReceiveLineAsync().ConfigureAwait(false); + if (line.Length < 1) + { + break; + } + + lines.Add(line); + } + + if (lines.Count < 1) + { + throw new InvalidDataException("HTTP request line not found"); + } + + var parts = lines[0].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length < 2) + { + throw new InvalidDataException("Malformed HTTP request line"); + } + + var method = parts[0].Trim().ToUpperInvariant(); + if (!WebRequest.Methods.Contains(method)) + { + throw new InvalidDataException("Unrecognized HTTP method"); + } + + var requestUrl = parts[1].Trim(); + if (string.IsNullOrEmpty(requestUrl)) + { + throw new InvalidDataException("Invalid HTTP request URI"); + } + + var headers = new NameValueCollection(StringComparer.OrdinalIgnoreCase); + for (var index = 1; index < lines.Count; index++) + { + var line = lines[index]; + + var pos = line.IndexOf(':'); + if (pos < 0) + { + throw new InvalidDataException("Malformed HTTP header line"); + } + + var name = line.Substring(0, pos).Trim(); + if (string.IsNullOrEmpty(name)) + { + throw new InvalidDataException("Malformed HTTP header line"); + } + + var value = line.Substring(pos + 1).Trim(); + if (string.IsNullOrEmpty(value)) + { + throw new InvalidDataException("Malformed HTTP header line"); + } + + headers[name] = value; + } + + string hostName = null; + var port = -1; + + var hostHeader = headers.Get("Host"); + if (!string.IsNullOrEmpty(hostHeader)) + { + var pos = hostHeader.IndexOf(':'); + if (pos < 0) + { + hostName = hostHeader.Trim(); + } + else + { + hostName = hostHeader.Substring(0, pos).Trim(); + if (int.TryParse(hostHeader.Substring(pos + 1), out var tempPort)) + { + port = tempPort; + } + } + } + + if (string.IsNullOrEmpty(hostName)) + { + hostName = Dns.GetHostName(); + } + + if (port < 1) + { + port = ((IPEndPoint)socket.LocalEndPoint).Port; + } + + var uri = new Uri("http://" + hostName + ":" + port + "/"); + if (requestUrl != "*") + { + uri = new Uri(uri, requestUrl); + } + + return new WebContext(socket, uri, headers); + } + catch + { + Abort(socket, 400); + throw; + } + } + + public async Task AcceptWebSocketAsync() + { + if (!Request.IsWebSocketRequest) + { + throw new InvalidOperationException("The request is not a WebSocket handshake"); + } + + return await Response.AcceptWebSocketAsync(Request.Headers["Sec-WebSocket-Key"].Trim()).ConfigureAwait(false); + } + + private static void Abort(Socket socket, int statusCode) + { + using (new WebResponse(socket, statusCode)) + { + } + } + } +} diff --git a/Unity/Package/Runtime/Util/Web/WebContext.cs.meta b/Unity/Package/Runtime/Util/Web/WebContext.cs.meta new file mode 100644 index 000000000..7fd2d2299 --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2fdc0ea215a06fe47b7e36ef2132f9f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Web/WebRequest.cs b/Unity/Package/Runtime/Util/Web/WebRequest.cs new file mode 100644 index 000000000..7907a96bd --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebRequest.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Specialized; + +namespace Microsoft.ClearScript.Util.Web +{ + internal sealed class WebRequest + { + internal static readonly string[] Methods = { "GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH" }; + + public bool IsWebSocketRequest { get; } + + public Uri Uri { get; } + + public string RawUrl { get; } + + public NameValueCollection Headers { get; } + + internal WebRequest(Uri uri, NameValueCollection headers) + { + Uri = uri; + RawUrl = Uri.PathAndQuery; + Headers = headers; + + IsWebSocketRequest = + string.Equals(headers["Connection"], "Upgrade", StringComparison.OrdinalIgnoreCase) && + string.Equals(headers["Upgrade"], "WebSocket", StringComparison.OrdinalIgnoreCase) && + !string.IsNullOrWhiteSpace(headers["Sec-WebSocket-Key"]); + } + } +} diff --git a/Unity/Package/Runtime/Util/Web/WebRequest.cs.meta b/Unity/Package/Runtime/Util/Web/WebRequest.cs.meta new file mode 100644 index 000000000..fc89528de --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f13c809c0360aa4883d8b4039186f0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Web/WebResponse.cs b/Unity/Package/Runtime/Util/Web/WebResponse.cs new file mode 100644 index 000000000..69b776b78 --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebResponse.cs @@ -0,0 +1,145 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.Util.Web +{ + internal sealed class WebResponse : IDisposable + { + private readonly Socket socket; + private int state; + + public int StatusCode { get; set; } + + public string ContentType { get; set; } + + public Stream OutputStream { get; } + + internal WebResponse(Socket socket, int statusCode) + { + this.socket = socket; + state = State.Open; + + StatusCode = statusCode; + OutputStream = new MemoryStream(); + } + + internal async Task AcceptWebSocketAsync(string key) + { + if (Interlocked.CompareExchange(ref state, State.Upgraded, State.Open) == State.Open) + { + using (var stream = CreateWebSocketResponseStream(key)) + { + await socket.SendBytesAsync(stream.GetBuffer(), 0, Convert.ToInt32(stream.Length)).ConfigureAwait(false); + } + + return new WebSocket(socket, true); + } + + throw new InvalidOperationException("Cannot accept a WebSocket connection in the current state"); + } + + public void Close(int? overrideStatusCode = null) + { + if (Interlocked.CompareExchange(ref state, State.Closed, State.Open) == State.Open) + { + CloseAsync(overrideStatusCode).ContinueWith(task => MiscHelpers.Try(task.Wait)); + } + } + + private async Task CloseAsync(int? overrideStatusCode) + { + using (socket) + { + using (var stream = CreateResponseStream(overrideStatusCode)) + { + await socket.SendBytesAsync(stream.GetBuffer(), 0, Convert.ToInt32(stream.Length)).ConfigureAwait(false); + } + } + } + + private MemoryStream CreateResponseStream(int? overrideStatusCode) + { + var stream = new MemoryStream(); + + using (var writer = new StreamWriter(stream, Encoding.ASCII, 16 * 1024, true)) + { + var statusCode = overrideStatusCode ?? StatusCode; + writer.Write("HTTP/1.1 {0} {1}\r\n", statusCode, Enum.GetName(typeof(HttpStatusCode), statusCode) ?? string.Empty); + + if (!string.IsNullOrWhiteSpace(ContentType)) + { + writer.Write("Content-Type: {0}\r\n", ContentType); + } + + if (OutputStream.Length > 0) + { + writer.Write("Content-Length: {0}\r\n", OutputStream.Length); + } + + writer.Write("Cache-Control: no-cache, no-store, must-revalidate\r\n"); + writer.Write("Connection: close\r\n"); + + writer.Write("\r\n"); + writer.Flush(); + } + + if (OutputStream.Length > 0) + { + stream.Write(((MemoryStream)OutputStream).GetBuffer(), 0, Convert.ToInt32(OutputStream.Length)); + } + + return stream; + } + + private static MemoryStream CreateWebSocketResponseStream(string key) + { + var stream = new MemoryStream(); + + using (var writer = new StreamWriter(stream, Encoding.ASCII, 16 * 1024, true)) + { + const int statusCode = 101; + writer.Write("HTTP/1.1 {0} {1}\r\n", statusCode, Enum.GetName(typeof(HttpStatusCode), statusCode) ?? string.Empty); + + writer.Write("Connection: Upgrade\r\n"); + writer.Write("Upgrade: websocket\r\n"); + + var acceptKey = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))); + writer.Write("Sec-WebSocket-Accept: {0}\r\n", acceptKey); + + writer.Write("\r\n"); + writer.Flush(); + } + + return stream; + } + + #region IDisposable implementation + + public void Dispose() + { + Close(); + } + + #endregion + + #region Nested type: State + + private static class State + { + public const int Open = 0; + public const int Upgraded = 1; + public const int Closed = 2; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/Web/WebResponse.cs.meta b/Unity/Package/Runtime/Util/Web/WebResponse.cs.meta new file mode 100644 index 000000000..f8c156e99 --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40f11f8dea804194cb3561d41ca68a72 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/Web/WebSocket.cs b/Unity/Package/Runtime/Util/Web/WebSocket.cs new file mode 100644 index 000000000..44fde5651 --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebSocket.cs @@ -0,0 +1,452 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.Util.Web +{ + [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "This class uses a custom method for deterministic teardown.")] + internal sealed class WebSocket + { + #region data + + private readonly Socket socket; + private readonly bool isServerSocket; + + private readonly Random random = MiscHelpers.CreateSeededRandom(); + private readonly SemaphoreSlim receiveSemaphore = new SemaphoreSlim(1); + private readonly SemaphoreSlim sendSemaphore = new SemaphoreSlim(1); + + private readonly InterlockedOneWayFlag closedFlag = new InterlockedOneWayFlag(); + + #endregion + + #region constructors + + internal WebSocket(Socket socket, bool isServerSocket) + { + this.socket = socket; + this.isServerSocket = isServerSocket; + } + + #endregion + + #region message I/O + + public async Task ReceiveMessageAsync() + { + using (await receiveSemaphore.CreateLockScopeAsync().ConfigureAwait(false)) + { + bool? isBinary = null; + var payloads = new List(); + + while (true) + { + var frame = await ReceiveFrameAsync().ConfigureAwait(false); + + if (frame.OpCode == OpCodes.Text) + { + if (isBinary.HasValue) + { + throw new Exception(ErrorCode.ProtocolError, "Received unexpected text frame from WebSocket"); + } + + isBinary = false; + + payloads.Add(frame.Payload); + if (frame.Final) + { + break; + } + } + else if (frame.OpCode == OpCodes.Binary) + { + if (isBinary.HasValue) + { + throw new Exception(ErrorCode.ProtocolError, "Received unexpected binary frame from WebSocket"); + } + + isBinary = true; + + payloads.Add(frame.Payload); + if (frame.Final) + { + break; + } + } + else if (frame.OpCode == OpCodes.Continuation) + { + if (!isBinary.HasValue) + { + throw new Exception(ErrorCode.ProtocolError, "Received unexpected continuation frame from WebSocket"); + } + + payloads.Add(frame.Payload); + if (frame.Final) + { + break; + } + } + else if (frame.OpCode == OpCodes.Ping) + { + var response = new Frame { Final = true, OpCode = OpCodes.Pong, Payload = frame.Payload }; + await SendFrameAsync(response).ConfigureAwait(false); + } + else if (frame.OpCode == OpCodes.Pong) + { + } + else if (frame.OpCode == OpCodes.Close) + { + var errorCode = ErrorCode.NormalClosure; + var message = "The WebSocket was closed by the remote endpoint"; + + if (frame.Payload.Length >= 2) + { + errorCode = (ErrorCode)frame.Payload.ToHostUInt16(); + if (frame.Payload.Length > 2) + { + message = Encoding.UTF8.GetString(frame.Payload, 2, frame.Payload.Length - 2); + } + } + + throw new Exception(errorCode, message); + } + else + { + throw new Exception(ErrorCode.ProtocolError, "Received unrecognized frame from WebSocket"); + } + } + + var length = 0L; + + var overflow = false; + try + { + length = payloads.Aggregate(0L, (tempLength, segment) => checked(tempLength + segment.LongLength)); + } + catch (OverflowException) + { + overflow = true; + } + + const long maxLength = 64 * 1024 * 1024; + if (overflow || (length > maxLength)) + { + throw new Exception(ErrorCode.MessageTooBig, "Incoming WebSocket message payload is too large"); + } + + var fullPayload = new byte[length]; + + var index = 0L; + foreach (var payload in payloads) + { + Array.Copy(payload, 0L, fullPayload, index, payload.LongLength); + index += payload.LongLength; + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + Debug.Assert(isBinary.HasValue); + + return new Message { IsBinary = isBinary.Value, Payload = fullPayload }; + } + } + + public Task SendMessageAsync(byte[] payload, bool isBinary = false) + { + var frame = new Frame { Final = true, OpCode = isBinary ? OpCodes.Binary : OpCodes.Text, Payload = payload }; + return SendFrameAsync(frame); + } + + #endregion + + #region frame I/O + + private async Task ReceiveFrameAsync() + { + var header = await socket.ReceiveBytesAsync(2).ConfigureAwait(false); + + var final = header[0].Has(HeaderBits.Final); + var opCode = header[0].And(HeaderBits.OpCodeMask); + var masked = header[1].Has(HeaderBits.Masked); + + ulong length = header[1].And(HeaderBits.LengthMask); + if (length == 126) + { + var lengthBytes = await socket.ReceiveBytesAsync(2).ConfigureAwait(false); + length = lengthBytes.ToHostUInt16(); + } + else if (length == 127) + { + var lengthBytes = await socket.ReceiveBytesAsync(8).ConfigureAwait(false); + length = lengthBytes.ToHostUInt64() & 0x7FFFFFFFFFFFFFFF; + } + + byte[] key = null; + if (masked) + { + key = await socket.ReceiveBytesAsync(4).ConfigureAwait(false); + } + + const ulong maxLength = 64 * 1024 * 1024; + if (length > maxLength) + { + throw new Exception(ErrorCode.MessageTooBig, "Incoming WebSocket frame payload is too large"); + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + Debug.Assert(length < long.MaxValue); + + var payload = new byte[length]; + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (length <= int.MaxValue) + { + await socket.ReceiveBytesAsync(payload, 0, Convert.ToInt32(length)).ConfigureAwait(false); + } + else + { + const int segmentLength = 1024 * 1024; + var segment = new byte[segmentLength]; + + var index = 0L; + for (; length > segmentLength; index += segmentLength) + { + await socket.ReceiveBytesAsync(segment, 0, segmentLength).ConfigureAwait(false); + Array.Copy(segment, 0L, payload, index, segmentLength); + length -= segmentLength; + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + Debug.Assert(length < int.MaxValue); + + var remainingLength = Convert.ToInt32(length); + + if (remainingLength > 0) + { + await socket.ReceiveBytesAsync(segment, 0, remainingLength).ConfigureAwait(false); + Array.Copy(segment, 0L, payload, index, remainingLength); + } + } + + if (masked) + { + for (var index = 0L; index < payload.LongLength; index++) + { + payload[index] ^= key[index % 4]; + } + } + + return new Frame { Final = final, OpCode = opCode, Payload = payload }; + } + + private async Task SendFrameAsync(Frame frame) + { + using (await sendSemaphore.CreateLockScopeAsync().ConfigureAwait(false)) + { + var header = new byte[2]; + var masked = !isServerSocket; + + header[0] = frame.OpCode.And(HeaderBits.OpCodeMask); + if (masked) + { + header[1] = HeaderBits.Masked; + } + + if (frame.Final) + { + header[0] = header[0].Or(HeaderBits.Final); + } + + var length = frame.Payload.LongLength; + byte[] lengthBytes = null; + + if (length <= 125) + { + header[1] = header[1].Or(Convert.ToByte(length)); + } + else if (length <= ushort.MaxValue) + { + header[1] = header[1].Or(126); + lengthBytes = Convert.ToUInt16(length).ToNetworkBytes(); + } + else + { + header[1] = header[1].Or(127); + lengthBytes = Convert.ToUInt64(length).ToNetworkBytes(); + } + + await socket.SendBytesAsync(header).ConfigureAwait(false); + if (lengthBytes != null) + { + await socket.SendBytesAsync(lengthBytes).ConfigureAwait(false); + } + + byte[] key = null; + if (masked) + { + key = new byte[4]; + random.NextBytes(key); + + await socket.SendBytesAsync(key).ConfigureAwait(false); + } + + const int segmentLength = 1024 * 1024; // must be a multiple of 4 + var segment = new byte[segmentLength]; + + var index = 0L; + for (; length > segmentLength; index += segmentLength) + { + Array.Copy(frame.Payload, index, segment, 0L, segmentLength); + + if (masked) + { + for (var segmentIndex = 0; segmentIndex < segmentLength; segmentIndex++) + { + segment[segmentIndex] ^= key[segmentIndex % 4]; + } + } + + await socket.SendBytesAsync(segment).ConfigureAwait(false); + length -= segmentLength; + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + Debug.Assert(length < int.MaxValue); + + var remainingLength = Convert.ToInt32(length); + + if (remainingLength > 0) + { + Array.Copy(frame.Payload, index, segment, 0L, remainingLength); + + if (masked) + { + for (var segmentIndex = 0; segmentIndex < remainingLength; segmentIndex++) + { + segment[segmentIndex] ^= key[segmentIndex % 4]; + } + } + + await socket.SendBytesAsync(segment, 0, remainingLength).ConfigureAwait(false); + } + } + } + + private void SendFrameAsync(Frame frame, Action callback) + { + SendFrameAsync(frame).ContinueWith(task => callback(MiscHelpers.Try(task.Wait))); + } + + #endregion + + #region teardown + + public void Close(ErrorCode errorCode, string message) + { + if (closedFlag.Set()) + { + var payload = ((ushort)errorCode).ToNetworkBytes(); + if (!string.IsNullOrEmpty(message)) + { + payload = payload.Concat(Encoding.UTF8.GetBytes(message)).ToArray(); + } + + var frame = new Frame { Final = true, OpCode = OpCodes.Close, Payload = payload }; + SendFrameAsync(frame, succeeded => + { + socket.Close(); + receiveSemaphore.Dispose(); + sendSemaphore.Dispose(); + }); + } + } + + #endregion + + #region Nested type: Message + + public sealed class Message + { + public bool IsBinary; + public byte[] Payload; + } + + #endregion + + #region Nested type: ErrorCode + + internal enum ErrorCode + { + NormalClosure = 1000, + EndpointUnavailable = 1001, + ProtocolError = 1002, + InvalidMessageType = 1003, + InvalidPayloadData = 1007, + PolicyViolation = 1008, + MessageTooBig = 1009 + } + + #endregion + + #region Nested type: Exception + + [Serializable] + public sealed class Exception : System.Exception + { + public ErrorCode ErrorCode { get; private set; } + + public Exception(ErrorCode errorCode, string message) + : base(message) + { + ErrorCode = errorCode; + } + } + + #endregion + + #region Nested type: HeaderBits + + private static class HeaderBits + { + public const byte Final = 0x80; + public const byte OpCodeMask = 0x0F; + public const byte Masked = 0x80; + public const byte LengthMask = 0x7F; + } + + #endregion + + #region Nested type: OpCodes + + private static class OpCodes + { + public const byte Continuation = 0x00; + public const byte Text = 0x01; + public const byte Binary = 0x02; + public const byte Close = 0x08; + public const byte Ping = 0x09; + public const byte Pong = 0x0A; + } + + #endregion + + #region Nested type: Frame + + private sealed class Frame + { + public bool Final; + public byte OpCode; + public byte[] Payload; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/Util/Web/WebSocket.cs.meta b/Unity/Package/Runtime/Util/Web/WebSocket.cs.meta new file mode 100644 index 000000000..56eefe8ff --- /dev/null +++ b/Unity/Package/Runtime/Util/Web/WebSocket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff1c329416fee674e855746916b3efe0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/Util/_Exception.cs b/Unity/Package/Runtime/Util/_Exception.cs new file mode 100644 index 000000000..0be7d5afa --- /dev/null +++ b/Unity/Package/Runtime/Util/_Exception.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Reflection; +using System.Runtime.Serialization; + +namespace System.Runtime.InteropServices +{ + // ReSharper disable once InconsistentNaming + internal interface _Exception + { + string ToString(); + bool Equals(object obj); + int GetHashCode(); + Type GetType(); + string Message { get; } + Exception GetBaseException(); + string StackTrace { get; } + string HelpLink { get; set; } + string Source { get; set; } + void GetObjectData(SerializationInfo info, StreamingContext context); + Exception InnerException { get; } + MethodBase TargetSite { get; } + } +} diff --git a/Unity/Package/Runtime/Util/_Exception.cs.meta b/Unity/Package/Runtime/Util/_Exception.cs.meta new file mode 100644 index 000000000..466940098 --- /dev/null +++ b/Unity/Package/Runtime/Util/_Exception.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a71edfd80eb862240a0abc51d4a0f924 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8.meta b/Unity/Package/Runtime/V8.meta new file mode 100644 index 000000000..a2d22301b --- /dev/null +++ b/Unity/Package/Runtime/V8.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 05c51777b8a6b29439cb74ad6a100863 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/IV8DebugListener.cs b/Unity/Package/Runtime/V8/IV8DebugListener.cs new file mode 100644 index 000000000..7de5235c2 --- /dev/null +++ b/Unity/Package/Runtime/V8/IV8DebugListener.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + internal interface IV8DebugListener : IDisposable + { + void ConnectClient(); + void SendCommand(string command); + void DisconnectClient(); + } +} diff --git a/Unity/Package/Runtime/V8/IV8DebugListener.cs.meta b/Unity/Package/Runtime/V8/IV8DebugListener.cs.meta new file mode 100644 index 000000000..3ba68a251 --- /dev/null +++ b/Unity/Package/Runtime/V8/IV8DebugListener.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 034f2ad81623bce478ab6c0da6ae2c60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/IV8Object.cs b/Unity/Package/Runtime/V8/IV8Object.cs new file mode 100644 index 000000000..5beb01b37 --- /dev/null +++ b/Unity/Package/Runtime/V8/IV8Object.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.JavaScript; + +namespace Microsoft.ClearScript.V8 +{ + internal interface IV8Object : IDisposable + { + JavaScriptObjectKind ObjectKind { get; } + JavaScriptObjectFlags ObjectFlags { get; } + + int IdentityHash { get; } + + object GetProperty(string name); + bool TryGetProperty(string name, out object value); + void SetProperty(string name, object value); + bool DeleteProperty(string name); + string[] GetPropertyNames(bool includeIndices); + + object GetProperty(int index); + void SetProperty(int index, object value); + bool DeleteProperty(int index); + int[] GetPropertyIndices(); + + object Invoke(bool asConstructor, object[] args); + object InvokeMethod(string name, object[] args); + + bool IsPromise { get; } + bool IsArray { get; } + bool IsShared { get; } + + bool IsArrayBufferOrView { get; } + V8ArrayBufferOrViewKind ArrayBufferOrViewKind { get; } + V8ArrayBufferOrViewInfo GetArrayBufferOrViewInfo(); + void InvokeWithArrayBufferOrViewData(Action action); + } +} diff --git a/Unity/Package/Runtime/V8/IV8Object.cs.meta b/Unity/Package/Runtime/V8/IV8Object.cs.meta new file mode 100644 index 000000000..42da592fa --- /dev/null +++ b/Unity/Package/Runtime/V8/IV8Object.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ec3f29d05b38b84cac03c27444e1d37 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy.meta b/Unity/Package/Runtime/V8/SplitProxy.meta new file mode 100644 index 000000000..ce58915eb --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed93072514374814682af97e96555c9c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs b/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs new file mode 100644 index 000000000..4fc67aece --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs @@ -0,0 +1,116 @@ +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + /// + /// Implement this interface to talk to ClearScript's native wrapper around V8 directly. + /// + public interface IV8HostObject + { + /// + /// Implement this to support getting the values of named properties. + /// + /// The name of the property JavaScript wants the value of. + /// Write the value of the property here. + /// If you set this to to true, V8 will cache the value not ask for it + /// again. + void GetNamedProperty(StdString name, V8Value value, out bool isConst) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support setting the values of named properties. + /// + /// The name of the property JavaScript wants to set. + /// The value JavaScript wants to set the property to. + void SetNamedProperty(StdString name, V8Value.Decoded value) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support deleting named properties. + /// + /// The name of the property JavaScript wants to delete. + /// TODO + bool DeleteNamedProperty(StdString name) => + throw new NotImplementedException($"Named property {name.ToString()} is not implemented"); + + /// + /// Implement this to support getting the values of indexed properties. + /// + /// The index of the property JavaScript wants the value of. + /// Write the value of the property here. + void GetIndexedProperty(int index, V8Value value) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support setting the values of indexed properties. + /// + /// The index of the property JavaScript wants to set. + /// The value JavaScript wants to set the property to. + void SetIndexedProperty(int index, V8Value.Decoded value) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support deleting indexed properties. + /// + /// The index of the property JavaScript wants to delete. + /// TODO + bool DeleteIndexedProperty(int index) => + throw new NotImplementedException($"Indexed property {index} is not implemented"); + + /// + /// Implement this to support being enumerated. + /// + /// Write the enumerator here. + /// + /// The enumerator class should implement and implement MoveNext(), + /// ScriptableDispose(), and CurrentValue. + /// + void GetEnumerator(V8Value result) => + throw new NotImplementedException("Enumerator is not implemented"); + + /// + /// Implement this to support being async enumerated. + /// + /// Write the async enumerator here. + void GetAsyncEnumerator(V8Value result) => + throw new NotImplementedException("Async enumerator is not implemented"); + + /// + /// Implement this to support listing of all your named proeprties. + /// + /// Write the names of your properties here. + void GetNamedPropertyNames(StdStringArray names) => + throw new NotImplementedException("Listing named properties is not implemented"); + + /// + /// Implement this to support listing all your indexed properties. + /// + /// Write the indices of your properties here. + void GetIndexedPropertyIndices(StdInt32Array indices) => + throw new NotImplementedException("Listing indexed properties is not implemented"); + + /// + /// I don't know when ClearScript calls this. + /// + /// The name of the method JavaScript wants to invoke. + /// The arguments JavaScript is passing to the method. + /// Write the return value, if not , of the method here. + /// + void InvokeMethod(StdString name, ReadOnlySpan args, V8Value result) + { + GetNamedProperty(name, result, out _); + object method = result.Decode().GetHostObject(); + result.SetNonexistent(); + ((InvokeHostObject)method)(args, result); + } + } + + /// + /// Return a delegate of this type from a property to tell JavaScript that it is a callable + /// function. + /// + /// The arguments JavaScript will pass to your method when invoking it. + /// Write the return value, if not , of the method here. + /// + public delegate void InvokeHostObject(ReadOnlySpan args, V8Value result); +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs.meta new file mode 100644 index 000000000..b3b41af9c --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/IV8HostObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88b2613c663682a43b483cff9183034d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs b/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs new file mode 100644 index 000000000..2aab1a990 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs @@ -0,0 +1,257 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal interface IV8SplitProxyNative + { + #region initialization + + IntPtr V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable); + string V8SplitProxyNative_GetVersion(); + void V8Environment_InitializeICU(IntPtr pICUData, uint size); + + #endregion + + #region StdString methods + + StdString.Ptr StdString_New(string value); + string StdString_GetValue(StdString.Ptr pString); + void StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length); + void StdString_SetValue(StdString.Ptr pString, string value); + void StdString_Delete(StdString.Ptr pString); + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr StdStringArray_New(int elementCount); + int StdStringArray_GetElementCount(StdStringArray.Ptr pArray); + void StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount); + string StdStringArray_GetElement(StdStringArray.Ptr pArray, int index); + void StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value); + void StdStringArray_Delete(StdStringArray.Ptr pArray); + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr StdByteArray_New(int elementCount); + int StdByteArray_GetElementCount(StdByteArray.Ptr pArray); + void StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount); + IntPtr StdByteArray_GetData(StdByteArray.Ptr pArray); + void StdByteArray_Delete(StdByteArray.Ptr pArray); + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr StdInt32Array_New(int elementCount); + int StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray); + void StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount); + IntPtr StdInt32Array_GetData(StdInt32Array.Ptr pArray); + void StdInt32Array_Delete(StdInt32Array.Ptr pArray); + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr StdUInt32Array_New(int elementCount); + int StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray); + void StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount); + IntPtr StdUInt32Array_GetData(StdUInt32Array.Ptr pArray); + void StdUInt32Array_Delete(StdUInt32Array.Ptr pArray); + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr StdUInt64Array_New(int elementCount); + int StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray); + void StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount); + IntPtr StdUInt64Array_GetData(StdUInt64Array.Ptr pArray); + void StdUInt64Array_Delete(StdUInt64Array.Ptr pArray); + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr StdPtrArray_New(int elementCount); + int StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray); + void StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount); + IntPtr StdPtrArray_GetData(StdPtrArray.Ptr pArray); + void StdPtrArray_Delete(StdPtrArray.Ptr pArray); + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr StdV8ValueArray_New(int elementCount); + int StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray); + void StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount); + V8Value.Ptr StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray); + void StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray); + + #endregion + + #region V8Value methods + + V8Value.Ptr V8Value_New(); + void V8Value_SetNonexistent(V8Value.Ptr pV8Value); + void V8Value_SetUndefined(V8Value.Ptr pV8Value); + void V8Value_SetNull(V8Value.Ptr pV8Value); + void V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value); + void V8Value_SetNumber(V8Value.Ptr pV8Value, double value); + void V8Value_SetInt32(V8Value.Ptr pV8Value, int value); + void V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value); + void V8Value_SetString(V8Value.Ptr pV8Value, string value); + void V8Value_SetDateTime(V8Value.Ptr pV8Value, double value); + void V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes); + void V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags); + void V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject); + void V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded); + void V8Value_Delete(V8Value.Ptr pV8Value); + + #endregion + + #region V8CpuProfile methods + + void V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode); + bool V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp); + void V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount); + bool V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts); + V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index); + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort); + V8Context.Handle V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort); + UIntPtr V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate); + void V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size); + double V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate); + void V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds); + UIntPtr V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate); + void V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size); + void V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate); + void V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate); + V8Script.Handle V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code); + V8Script.Handle V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); + V8Script.Handle V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); + V8Script.Handle V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult); + bool V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate); + void V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value); + bool V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate); + void V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value); + void V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize); + void V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts); + void V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive); + bool V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples); + void V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction); + void V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate); + uint V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate); + void V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value); + void V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream); + + #endregion + + #region V8 context methods + + UIntPtr V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext); + void V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size); + double V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext); + void V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds); + UIntPtr V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext); + void V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size); + void V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction); + object V8Context_GetRootItem(V8Context.Handle hContext); + void V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers); + void V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext); + void V8Context_CancelAwaitDebugger(V8Context.Handle hContext); + object V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate); + void V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult); + V8Script.Handle V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code); + V8Script.Handle V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); + V8Script.Handle V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); + V8Script.Handle V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult); + object V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate); + void V8Context_Interrupt(V8Context.Handle hContext); + void V8Context_CancelInterrupt(V8Context.Handle hContext); + bool V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext); + void V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value); + bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext); + void V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value); + void V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize); + void V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts); + void V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize); + void V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive); + void V8Context_OnAccessSettingsChanged(V8Context.Handle hContext); + bool V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples); + void V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction); + void V8Context_CollectCpuProfileSample(V8Context.Handle hContext); + uint V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext); + void V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value); + void V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream); + + #endregion + + #region V8 object methods + + object V8Object_GetNamedProperty(V8Object.Handle hObject, string name); + void V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue); + bool V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value); + void V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value); + bool V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name); + string[] V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices); + object V8Object_GetIndexedProperty(V8Object.Handle hObject, int index); + void V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue); + void V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value); + bool V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index); + int[] V8Object_GetPropertyIndices(V8Object.Handle hObject); + object V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args); + void V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult); + object V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args); + void V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length); + void V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length); + void V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction); + + #endregion + + #region V8 debug callback methods + + void V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback); + void V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command); + void V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback); + + #endregion + + #region native callback methods + + void NativeCallback_Invoke(NativeCallback.Handle hCallback); + + #endregion + + #region V8 entity cleanup + + void V8Entity_Release(V8Entity.Handle hEntity); + void V8Entity_DestroyHandle(V8Entity.Handle hEntity); + + #endregion + + #region error handling + + void HostException_Schedule(string message, object exception); + + #endregion + + #region unit test support + + UIntPtr V8UnitTestSupport_GetTextDigest(string value); + void V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount); + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs.meta new file mode 100644 index 000000000..b71df614b --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/IV8SplitProxyNative.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0437f59a86a718848a962b019d43d8cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs new file mode 100644 index 000000000..5b2c23a2f --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class NativeCallbackImpl : INativeCallback + { + private V8EntityHolder holder; + + private NativeCallback.Handle Handle => (NativeCallback.Handle)holder.Handle; + + public NativeCallbackImpl(NativeCallback.Handle hCallback) + { + holder = new V8EntityHolder("native callback", () => hCallback); + } + + #region INativeCallback implementation + + public void Invoke() + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.NativeCallback_Invoke(Handle); + } + } + + #endregion + + #region disposal / finalization + + public void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~NativeCallbackImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs.meta new file mode 100644 index 000000000..d604359a7 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/NativeCallbackImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8ef42dd0460dba41ad4212d4dc22d39 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs b/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs new file mode 100644 index 000000000..f6b89a721 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + /// + /// Wraps a Uint8Array, an array of . + /// + public readonly ref struct Uint8Array + { + private readonly V8Object.Handle ptr; + + internal Uint8Array(V8Object.Handle pArray) + { + ptr = pArray; + using var arrayBuffer = V8Value.New(); + + V8SplitProxyNative.Instance.V8Object_GetArrayBufferOrViewInfo(pArray, arrayBuffer.ptr, + out _, out _, out ulong length); + + Length = (int)length; + } + + /// + /// Copy the contents of the wrapped Uint8Array to a managed array. + /// + /// The destination array. It must be large enough to contain the entire + /// contents of the wrapped Uint8Array. + public void CopyTo(byte[] array) + { + int length = Length; + + if (length > array.Length) + throw new IndexOutOfRangeException( + $"Tried to copy {length} items to a {array.Length} item array"); + + // TODO: Don't allocate a lambda every time. + IntPtr pAction = V8ProxyHelpers.AddRefHostObject(new Action(data => + Marshal.Copy(data, array, 0, length))); + + try + { + V8SplitProxyNative.Instance.V8Object_InvokeWithArrayBufferOrViewData(ptr, pAction); + } + finally + { + V8ProxyHelpers.ReleaseHostObject(pAction); + } + } + + /// + /// The length of the wrapped Uint8Array. + /// + public int Length { get; } + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs.meta new file mode 100644 index 000000000..7481d76d8 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/Uint8Array.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9eac5c6309b410046927c36e29fb87fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs new file mode 100644 index 000000000..d8f591a95 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs @@ -0,0 +1,469 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8ContextProxyImpl : V8ContextProxy + { + private V8EntityHolder holder; + + internal V8Context.Handle Handle => (V8Context.Handle)holder.Handle; + + public V8ContextProxyImpl(V8IsolateProxy isolateProxy, string name, V8ScriptEngineFlags flags, int debugPort) + { + holder = new V8EntityHolder("V8 script engine", () => ((V8IsolateProxyImpl)isolateProxy).CreateContext(name, flags, debugPort)); + } + + #region V8ContextProxy overrides + + public override UIntPtr MaxIsolateHeapSize + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetMaxIsolateHeapSize(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetMaxIsolateHeapSize(Handle, value); + } + } + } + + public override TimeSpan IsolateHeapSizeSampleInterval + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return TimeSpan.FromMilliseconds(instance.V8Context_GetIsolateHeapSizeSampleInterval(Handle)); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetIsolateHeapSizeSampleInterval(Handle, value.TotalMilliseconds); + } + } + } + + public override UIntPtr MaxIsolateStackUsage + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetMaxIsolateStackUsage(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetMaxIsolateStackUsage(Handle, value); + } + } + } + + public override void InvokeWithLock(Action action) + { + using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_InvokeWithLock(Handle, actionScope.Value); + } + } + } + + public override object GetRootItem() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetRootItem(Handle); + } + } + + public override void AddGlobalItem(string name, object item, bool globalMembers) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_AddGlobalItem(Handle, name, item, globalMembers); + } + } + + public override void AwaitDebuggerAndPause() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_AwaitDebuggerAndPause(Handle); + } + } + + public override void CancelAwaitDebugger() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CancelAwaitDebugger(Handle); + } + } + + public override object Execute(UniqueDocumentInfo documentInfo, string code, bool evaluate) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_ExecuteCode( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + evaluate + ); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_Compile( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + if (cacheKind == V8CacheKind.None) + { + cacheBytes = null; + return Compile(documentInfo, code); + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileProducingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + out cacheBytes + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + if ((cacheKind == V8CacheKind.None) || (cacheBytes == null) || (cacheBytes.Length < 1)) + { + cacheAccepted = false; + return Compile(documentInfo, code); + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileConsumingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + cacheBytes, + out cacheAccepted + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + if (cacheKind == V8CacheKind.None) + { + cacheResult = V8CacheResult.Disabled; + return Compile(documentInfo, code); + } + + V8.V8Script script; + var tempCacheBytes = cacheBytes; + + if ((cacheBytes == null) || (cacheBytes.Length < 1)) + { + script = Compile(documentInfo, code, cacheKind, out tempCacheBytes); + cacheResult = (tempCacheBytes != null) && (tempCacheBytes.Length > 0) ? V8CacheResult.Updated : V8CacheResult.UpdateFailed; + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = tempCacheBytes; + } + + return script; + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + script = new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Context_CompileUpdatingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + ref cacheBytes, + out cacheResult + )); + } + + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = tempCacheBytes; + } + + return script; + } + + public override object Execute(V8.V8Script script, bool evaluate) + { + if (!(script is V8ScriptImpl scriptImpl)) + { + throw new ArgumentException("Invalid compiled script", nameof(script)); + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_ExecuteScript( + Handle, + scriptImpl.Handle, + evaluate + ); + } + } + + public override void Interrupt() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_Interrupt(Handle); + } + } + + public override void CancelInterrupt() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CancelInterrupt(Handle); + } + } + + public override bool EnableIsolateInterruptPropagation + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetEnableIsolateInterruptPropagation(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetEnableIsolateInterruptPropagation(Handle, value); + } + } + } + + public override bool DisableIsolateHeapSizeViolationInterrupt + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(Handle, value); + } + } + } + + public override V8RuntimeHeapInfo GetIsolateHeapInfo() + { + var totalHeapSize = 0UL; + var totalHeapSizeExecutable = 0UL; + var totalPhysicalSize = 0UL; + var totalAvailableSize = 0UL; + var usedHeapSize = 0UL; + var heapSizeLimit = 0UL; + var totalExternalSize = 0UL; + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetIsolateHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + return new V8RuntimeHeapInfo + { + TotalHeapSize = totalHeapSize, + TotalHeapSizeExecutable = totalHeapSizeExecutable, + TotalPhysicalSize = totalPhysicalSize, + TotalAvailableSize = totalAvailableSize, + UsedHeapSize = usedHeapSize, + HeapSizeLimit = heapSizeLimit, + TotalExternalSize = totalExternalSize + }; + } + + public override V8Runtime.Statistics GetIsolateStatistics() + { + var statistics = new V8Runtime.Statistics(); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetIsolateStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts); + } + + return statistics; + } + + public override V8ScriptEngine.Statistics GetStatistics() + { + var statistics = new V8ScriptEngine.Statistics(); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ModuleCount, out statistics.ModuleCacheSize); + } + + return statistics; + } + + public override void CollectGarbage(bool exhaustive) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CollectGarbage(Handle, exhaustive); + } + } + + public override void OnAccessSettingsChanged() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_OnAccessSettingsChanged(Handle); + } + } + + public override bool BeginCpuProfile(string name, V8CpuProfileFlags flags) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection)); + } + } + + public override V8.V8CpuProfile EndCpuProfile(string name) + { + var profile = new V8.V8CpuProfile(); + + Action action = pProfile => V8CpuProfile.ProcessProfile(Handle, pProfile, profile); + using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_EndCpuProfile(Handle, name, actionScope.Value); + } + } + + return profile; + } + + public override void CollectCpuProfileSample() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_CollectCpuProfileSample(Handle); + } + } + + public override uint CpuProfileSampleInterval + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Context_GetCpuProfileSampleInterval(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_SetCpuProfileSampleInterval(Handle, value); + } + } + } + + public override void WriteIsolateHeapSnapshot(Stream stream) + { + using (var streamScope = V8ProxyHelpers.CreateAddRefHostObjectScope(stream)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Context_WriteIsolateHeapSnapshot(Handle, streamScope.Value); + } + } + } + + #endregion + + #region disposal / finalization + + public override void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~V8ContextProxyImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs.meta new file mode 100644 index 000000000..f4614d9cd --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ContextProxyImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fa3209ce7648f7489d2a940f3fcfb8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs new file mode 100644 index 000000000..ba1224c56 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8DebugListenerImpl : IV8DebugListener + { + private V8EntityHolder holder; + + private V8DebugCallback.Handle Handle => (V8DebugCallback.Handle)holder.Handle; + + public V8DebugListenerImpl(V8DebugCallback.Handle hCallback) + { + holder = new V8EntityHolder("V8 debug listener", () => hCallback); + } + + #region IV8DebugListener implementation + + public void ConnectClient() + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_ConnectClient(Handle); + } + } + + public void SendCommand(string command) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_SendCommand(Handle, command); + } + } + + public void DisconnectClient() + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8DebugCallback_DisconnectClient(Handle); + } + } + + #endregion + + #region disposal / finalization + + public void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~V8DebugListenerImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs.meta new file mode 100644 index 000000000..4dbe3e3a2 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8DebugListenerImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 072b6aa4fa394ec4194bed37b47048c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs b/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs new file mode 100644 index 000000000..657951dd9 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal readonly struct V8EntityHolder + { + private readonly string name; + private readonly bool registered; + private readonly V8Entity.Handle handle; + + public V8Entity.Handle Handle => (handle != V8Entity.Handle.Empty) ? handle : throw new InvalidOperationException("The " + name + " proxy has been destroyed"); + + public V8EntityHolder(string name, Func acquireHandle) + { + this.name = name; + V8Proxy.OnEntityHolderCreated(); + registered = true; + handle = acquireHandle(); + } + + private V8EntityHolder(string name) + { + this.name = name; + registered = false; + handle = V8Entity.Handle.Empty; + } + + public void ReleaseEntity() + { + if (handle != V8Entity.Handle.Empty) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Entity_Release(handle); + } + } + } + + public static void Destroy(ref V8EntityHolder holder) + { + if (holder.handle != V8Entity.Handle.Empty) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Entity_DestroyHandle(holder.handle); + } + } + + if (holder.registered) + { + V8Proxy.OnEntityHolderDestroyed(); + } + + holder = new V8EntityHolder(holder.name); + } + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs.meta new file mode 100644 index 000000000..399187212 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8EntityHolder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c728190f8c46d884185863917787331b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs new file mode 100644 index 000000000..d8ed6528a --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs @@ -0,0 +1,399 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8IsolateProxyImpl : V8IsolateProxy + { + private V8EntityHolder holder; + + private V8Isolate.Handle Handle => (V8Isolate.Handle)holder.Handle; + + public V8IsolateProxyImpl(string name, V8RuntimeConstraints constraints, V8RuntimeFlags flags, int debugPort) + { + holder = new V8EntityHolder("V8 runtime", () => + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_Create( + name, + constraints?.MaxNewSpaceSize ?? -1, + constraints?.MaxOldSpaceSize ?? -1, + constraints?.HeapExpansionMultiplier ?? 0, + constraints?.MaxArrayBufferAllocation ?? ulong.MaxValue, + flags, + debugPort + ); + } + }); + } + + public V8Context.Handle CreateContext(string name, V8ScriptEngineFlags flags, int debugPort) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_CreateContext( + Handle, + name, + flags, + debugPort + ); + } + } + + #region V8IsolateProxy overrides + + public override UIntPtr MaxHeapSize + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetMaxHeapSize(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetMaxHeapSize(Handle, value); + } + } + } + + public override TimeSpan HeapSizeSampleInterval + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return TimeSpan.FromMilliseconds(instance.V8Isolate_GetHeapSizeSampleInterval(Handle)); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetHeapSizeSampleInterval(Handle, value.TotalMilliseconds); + } + } + } + + public override UIntPtr MaxStackUsage + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetMaxStackUsage(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetMaxStackUsage(Handle, value); + } + } + } + + public override void AwaitDebuggerAndPause() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_AwaitDebuggerAndPause(Handle); + } + } + + public override void CancelAwaitDebugger() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CancelAwaitDebugger(Handle); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_Compile( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + if (cacheKind == V8CacheKind.None) + { + cacheBytes = null; + return Compile(documentInfo, code); + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileProducingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + out cacheBytes + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + if ((cacheKind == V8CacheKind.None) || (cacheBytes == null) || (cacheBytes.Length < 1)) + { + cacheAccepted = false; + return Compile(documentInfo, code); + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + return new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileConsumingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + cacheBytes, + out cacheAccepted + )); + } + } + + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + if (cacheKind == V8CacheKind.None) + { + cacheResult = V8CacheResult.Disabled; + return Compile(documentInfo, code); + } + + V8.V8Script script; + var tempCacheBytes = cacheBytes; + + if ((cacheBytes == null) || (cacheBytes.Length < 1)) + { + script = Compile(documentInfo, code, cacheKind, out tempCacheBytes); + cacheResult = (tempCacheBytes != null) && (tempCacheBytes.Length > 0) ? V8CacheResult.Updated : V8CacheResult.UpdateFailed; + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = tempCacheBytes; + } + + return script; + } + + using (V8SplitProxyNative.Invoke(out var instance)) + { + script = new V8ScriptImpl(documentInfo, code.GetDigest(), instance.V8Isolate_CompileUpdatingCache( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, + cacheKind, + ref tempCacheBytes, + out cacheResult + )); + } + + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = tempCacheBytes; + } + + return script; + } + + public override bool EnableInterruptPropagation + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetEnableInterruptPropagation(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetEnableInterruptPropagation(Handle, value); + } + } + } + + public override bool DisableHeapSizeViolationInterrupt + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetDisableHeapSizeViolationInterrupt(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetDisableHeapSizeViolationInterrupt(Handle, value); + } + } + } + + public override V8RuntimeHeapInfo GetHeapInfo() + { + var totalHeapSize = 0UL; + var totalHeapSizeExecutable = 0UL; + var totalPhysicalSize = 0UL; + var totalAvailableSize = 0UL; + var usedHeapSize = 0UL; + var heapSizeLimit = 0UL; + var totalExternalSize = 0UL; + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_GetHeapStatistics(Handle, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + return new V8RuntimeHeapInfo + { + TotalHeapSize = totalHeapSize, + TotalHeapSizeExecutable = totalHeapSizeExecutable, + TotalPhysicalSize = totalPhysicalSize, + TotalAvailableSize = totalAvailableSize, + UsedHeapSize = usedHeapSize, + HeapSizeLimit = heapSizeLimit, + TotalExternalSize = totalExternalSize + }; + } + + public override V8Runtime.Statistics GetStatistics() + { + var statistics = new V8Runtime.Statistics(); + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_GetStatistics(Handle, out statistics.ScriptCount, out statistics.ScriptCacheSize, out statistics.ModuleCount, out statistics.PostedTaskCounts, out statistics.InvokedTaskCounts); + } + + return statistics; + } + + public override void CollectGarbage(bool exhaustive) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CollectGarbage(Handle, exhaustive); + } + } + + public override bool BeginCpuProfile(string name, V8CpuProfileFlags flags) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_BeginCpuProfile(Handle, name, flags.HasFlag(V8CpuProfileFlags.EnableSampleCollection)); + } + } + + public override V8.V8CpuProfile EndCpuProfile(string name) + { + var profile = new V8.V8CpuProfile(); + + Action action = pProfile => V8CpuProfile.ProcessProfile(Handle, pProfile, profile); + using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_EndCpuProfile(Handle, name, actionScope.Value); + } + } + + return profile; + } + + public override void CollectCpuProfileSample() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_CollectCpuProfileSample(Handle); + } + } + + public override uint CpuProfileSampleInterval + { + get + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Isolate_GetCpuProfileSampleInterval(Handle); + } + } + + set + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_SetCpuProfileSampleInterval(Handle, value); + } + } + } + + public override void WriteHeapSnapshot(Stream stream) + { + using (var streamScope = V8ProxyHelpers.CreateAddRefHostObjectScope(stream)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Isolate_WriteHeapSnapshot(Handle, streamScope.Value); + } + } + } + + #endregion + + #region disposal / finalization + + public override void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~V8IsolateProxyImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs.meta new file mode 100644 index 000000000..025ebbaf6 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8IsolateProxyImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbf52b66f4b0bbd4ab7c66704a56b08f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs new file mode 100644 index 000000000..b0daded49 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs @@ -0,0 +1,320 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.JavaScript; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8ObjectImpl : IV8Object + { + private V8EntityHolder holder; + + public V8Object.Handle Handle => (V8Object.Handle)holder.Handle; + + public V8ObjectImpl(V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags, int identityHash) + { + holder = new V8EntityHolder("V8 object", () => hObject); + Subtype = subtype; + Flags = flags; + IdentityHash = identityHash; + } + + public V8Value.Subtype Subtype { get; } + + public V8Value.Flags Flags { get; } + + #region IV8Object implementation + + public JavaScriptObjectKind ObjectKind + { + get + { + switch (Subtype) + { + case V8Value.Subtype.Function: + return JavaScriptObjectKind.Function; + + case V8Value.Subtype.Iterator: + return JavaScriptObjectKind.Iterator; + + case V8Value.Subtype.Promise: + return JavaScriptObjectKind.Promise; + + case V8Value.Subtype.Array: + return JavaScriptObjectKind.Array; + + case V8Value.Subtype.ArrayBuffer: + return JavaScriptObjectKind.ArrayBuffer; + + case V8Value.Subtype.DataView: + return JavaScriptObjectKind.DataView; + + case V8Value.Subtype.Uint8Array: + case V8Value.Subtype.Uint8ClampedArray: + case V8Value.Subtype.Int8Array: + case V8Value.Subtype.Uint16Array: + case V8Value.Subtype.Int16Array: + case V8Value.Subtype.Uint32Array: + case V8Value.Subtype.Int32Array: + case V8Value.Subtype.BigUint64Array: + case V8Value.Subtype.BigInt64Array: + case V8Value.Subtype.Float32Array: + case V8Value.Subtype.Float64Array: + return JavaScriptObjectKind.TypedArray; + + default: + return JavaScriptObjectKind.Unknown; + } + } + } + + public JavaScriptObjectFlags ObjectFlags + { + get + { + var flags = JavaScriptObjectFlags.None; + + if (Flags.HasFlag(V8Value.Flags.Shared)) + { + flags |= JavaScriptObjectFlags.Shared; + } + + if (Flags.HasFlag(V8Value.Flags.Async)) + { + flags |= JavaScriptObjectFlags.Async; + } + + if (Flags.HasFlag(V8Value.Flags.Generator)) + { + flags |= JavaScriptObjectFlags.Generator; + } + + return flags; + } + } + + public int IdentityHash { get; } + + public object GetProperty(string name) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetNamedProperty(Handle, name); + } + } + + public bool TryGetProperty(string name, out object value) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_TryGetNamedProperty(Handle, name, out value); + } + } + + public void SetProperty(string name, object value) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_SetNamedProperty(Handle, name, value); + } + } + + public bool DeleteProperty(string name) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_DeleteNamedProperty(Handle, name); + } + } + + public string[] GetPropertyNames(bool includeIndices) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetPropertyNames(Handle, includeIndices); + } + } + + public object GetProperty(int index) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetIndexedProperty(Handle, index); + } + } + + public void SetProperty(int index, object value) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_SetIndexedProperty(Handle, index, value); + } + } + + public bool DeleteProperty(int index) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_DeleteIndexedProperty(Handle, index); + } + } + + public int[] GetPropertyIndices() + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_GetPropertyIndices(Handle); + } + } + + public object Invoke(bool asConstructor, object[] args) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_Invoke(Handle, asConstructor, args); + } + } + + public object InvokeMethod(string name, object[] args) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + return instance.V8Object_InvokeMethod(Handle, name, args); + } + } + + public bool IsPromise => Subtype == V8Value.Subtype.Promise; + + public bool IsArray => Subtype == V8Value.Subtype.Array; + + public bool IsShared => Flags.HasFlag(V8Value.Flags.Shared); + + public bool IsArrayBufferOrView + { + get + { + switch (Subtype) + { + case V8Value.Subtype.ArrayBuffer: + case V8Value.Subtype.DataView: + case V8Value.Subtype.Uint8Array: + case V8Value.Subtype.Uint8ClampedArray: + case V8Value.Subtype.Int8Array: + case V8Value.Subtype.Uint16Array: + case V8Value.Subtype.Int16Array: + case V8Value.Subtype.Uint32Array: + case V8Value.Subtype.Int32Array: + case V8Value.Subtype.BigUint64Array: + case V8Value.Subtype.BigInt64Array: + case V8Value.Subtype.Float32Array: + case V8Value.Subtype.Float64Array: + return true; + + default: + return false; + } + } + } + + public V8ArrayBufferOrViewKind ArrayBufferOrViewKind + { + get + { + switch (Subtype) + { + case V8Value.Subtype.ArrayBuffer: + return V8ArrayBufferOrViewKind.ArrayBuffer; + + case V8Value.Subtype.DataView: + return V8ArrayBufferOrViewKind.DataView; + + case V8Value.Subtype.Uint8Array: + return V8ArrayBufferOrViewKind.Uint8Array; + + case V8Value.Subtype.Uint8ClampedArray: + return V8ArrayBufferOrViewKind.Uint8ClampedArray; + + case V8Value.Subtype.Int8Array: + return V8ArrayBufferOrViewKind.Int8Array; + + case V8Value.Subtype.Uint16Array: + return V8ArrayBufferOrViewKind.Uint16Array; + + case V8Value.Subtype.Int16Array: + return V8ArrayBufferOrViewKind.Int16Array; + + case V8Value.Subtype.Uint32Array: + return V8ArrayBufferOrViewKind.Uint32Array; + + case V8Value.Subtype.Int32Array: + return V8ArrayBufferOrViewKind.Int32Array; + + case V8Value.Subtype.BigUint64Array: + return V8ArrayBufferOrViewKind.BigUint64Array; + + case V8Value.Subtype.BigInt64Array: + return V8ArrayBufferOrViewKind.BigInt64Array; + + case V8Value.Subtype.Float32Array: + return V8ArrayBufferOrViewKind.Float32Array; + + case V8Value.Subtype.Float64Array: + return V8ArrayBufferOrViewKind.Float64Array; + + default: + return V8ArrayBufferOrViewKind.None; + } + } + } + + public V8ArrayBufferOrViewInfo GetArrayBufferOrViewInfo() + { + var kind = ArrayBufferOrViewKind; + if (kind != V8ArrayBufferOrViewKind.None) + { + IV8Object arrayBuffer = null; + var offset = 0UL; + var size = 0UL; + var length = 0UL; + + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_GetArrayBufferOrViewInfo(Handle, out arrayBuffer, out offset, out size, out length); + } + + return new V8ArrayBufferOrViewInfo(kind, arrayBuffer, offset, size, length); + } + + return null; + } + + public void InvokeWithArrayBufferOrViewData(Action action) + { + using (var actionScope = V8ProxyHelpers.CreateAddRefHostObjectScope(action)) + { + using (V8SplitProxyNative.Invoke(out var instance)) + { + instance.V8Object_InvokeWithArrayBufferOrViewData(Handle, actionScope.Value); + } + } + } + + #endregion + + #region disposal / finalization + + public void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~V8ObjectImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs.meta new file mode 100644 index 000000000..d5765e2a4 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ObjectImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0e46f90064896b44bb5182e7f48cdef2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs new file mode 100644 index 000000000..5d2ceb20d --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8ScriptImpl : V8.V8Script + { + private V8EntityHolder holder; + + public V8Script.Handle Handle => (V8Script.Handle)holder.Handle; + + public V8ScriptImpl(UniqueDocumentInfo documentInfo, UIntPtr codeDigest, V8Script.Handle hScript) + : base(documentInfo, codeDigest) + { + holder = new V8EntityHolder("V8 compiled script", () => hScript); + } + + #region disposal / finalization + + public override void Dispose() + { + holder.ReleaseEntity(); + GC.KeepAlive(this); + } + + ~V8ScriptImpl() + { + V8EntityHolder.Destroy(ref holder); + } + + #endregion + } +} \ No newline at end of file diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs.meta new file mode 100644 index 000000000..c7565972a --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8ScriptImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69953f3d251482a41bcfdccf8ecd88c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs new file mode 100644 index 000000000..5d6769329 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs @@ -0,0 +1,2637 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Numerics; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + #region native object helpers + + /// + /// Wraps an std::wstring. + /// + public readonly ref struct StdString + { + internal readonly Ptr ptr; + private readonly bool owns; + + /// + /// Create a new std::wstring. + /// + /// The contents of the new std::wstring. + public StdString(string value) + { + if (value != null) + { + ptr = V8SplitProxyNative.Instance.StdString_New(value); + owns = true; + } + else + { + ptr = Ptr.Null; + owns = false; + } + } + + internal StdString(Ptr pValue) + { + ptr = pValue; + owns = false; + } + + /// + /// Delete the wrapped std::wstring. + /// + public void Dispose() + { + if (owns) + { + V8SplitProxyNative.Instance.StdString_Delete(ptr); + } + } + + /// + /// Compare the wrapped std::wstring to a . + /// + /// The string to compare the wrapped std::wstring to. + /// True if the strings are byte for byte equal, false otherwise. + public bool Equals(string other) + { + if (ptr == Ptr.Null) + { + return other == null; + } + else if (other == null) + { + return false; + } + + V8SplitProxyNative.Instance.StdString_GetValue(ptr, out IntPtr value, out int length); + + if (length != other.Length) + { + return false; + } + else if (length == 0) + { + return true; + } + + unsafe + { + char* i = (char*)value; + char* end = i + length; + + fixed (char* otherPtr = other) + { + char* j = otherPtr; + + while (i < end) + { + if (*i != *j) + { + return false; + } + + i++; + j++; + } + } + } + + return true; + } + + /// + /// Create a new string with the contents of the wrapped std::wstring. + /// + /// A new managed string with the same contents as the wrapped std::wtring byte for byte. + public override string ToString() + { + return ptr != Ptr.Null ? GetValue(ptr) : null; + } + + internal static IScope CreateScope(string value = null) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdString_New(value ?? string.Empty), V8SplitProxyNative.Instance.StdString_Delete); + } + + internal static string GetValue(Ptr pString) + { + return V8SplitProxyNative.Instance.StdString_GetValue(pString); + } + + internal static void SetValue(Ptr pString, string value) + { + V8SplitProxyNative.Instance.StdString_SetValue(pString, value); + } + + #region Nested type: Ptr + + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + /// + /// Wraps an std::vector<std::wstring>. + /// + public readonly ref struct StdStringArray + { + private readonly Ptr ptr; + + internal StdStringArray(Ptr pValue) + { + ptr = pValue; + } + + /// + /// Set the length of the wrapped std::vector<std::wstring>. + /// + /// The new length + public void SetElementCount(int elementCount) + { + if (ptr != Ptr.Null) + throw new NullReferenceException("StdStringArray is uninitialized"); + + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(ptr, elementCount); + } + + internal static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdStringArray_New(elementCount), V8SplitProxyNative.Instance.StdStringArray_Delete); + } + + internal static IScope CreateScope(string[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdStringArray_Delete); + } + + internal static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdStringArray_GetElementCount(pArray); + } + + internal static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(pArray, elementCount); + } + + internal static string[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdStringArray_GetElementCount(pArray); + var array = new string[elementCount]; + + if (elementCount > 0) + { + for (var index = 0; index < elementCount; index++) + { + array[index] = V8SplitProxyNative.Instance.StdStringArray_GetElement(pArray, index); + } + } + + return array; + } + + internal static void CopyFromArray(Ptr pArray, string[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdStringArray_SetElementCount(pArray, elementCount); + + for (var index = 0; index < elementCount; index++) + { + V8SplitProxyNative.Instance.StdStringArray_SetElement(pArray, index, array[index]); + } + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, string[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdStringArray_New(elementCount); + + if (elementCount > 0) + { + for (var index = 0; index < elementCount; index++) + { + instance.StdStringArray_SetElement(pArray, index, array[index]); + } + } + + return pArray; + } + + #region Nested type: Ptr + + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class StdByteArray + { + public static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdByteArray_New(elementCount), V8SplitProxyNative.Instance.StdByteArray_Delete); + } + + public static IScope CreateScope(byte[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdByteArray_Delete); + } + + public static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdByteArray_GetElementCount(pArray); + } + + public static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdByteArray_SetElementCount(pArray, elementCount); + } + + public static byte[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdByteArray_GetElementCount(pArray); + var array = new byte[elementCount]; + + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdByteArray_GetData(pArray), array, 0, elementCount); + } + + return array; + } + + public static void CopyFromArray(Ptr pArray, byte[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdByteArray_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, V8SplitProxyNative.Instance.StdByteArray_GetData(pArray), elementCount); + } + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, byte[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdByteArray_New(elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, instance.StdByteArray_GetData(pArray), elementCount); + } + + return pArray; + } + + #region Nested type: Ptr + + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + /// + /// Wraps an std::vector<int32_t>. + /// + public readonly ref struct StdInt32Array + { + private readonly Ptr ptr; + + internal StdInt32Array(Ptr pValue) + { + ptr = pValue; + } + + /// + /// Set the length of the wrapped std::vector<int32_t>. + /// + /// The new length. + public void SetElementCount(int elementCount) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("StdInt32Array is uninitialized"); + + V8SplitProxyNative.Instance.StdInt32Array_SetElementCount(ptr, elementCount); + } + + internal static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdInt32Array_New(elementCount), V8SplitProxyNative.Instance.StdInt32Array_Delete); + } + + internal static IScope CreateScope(int[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdInt32Array_Delete); + } + + internal static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdInt32Array_GetElementCount(pArray); + } + + internal static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdInt32Array_SetElementCount(pArray, elementCount); + } + + internal static int[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdInt32Array_GetElementCount(pArray); + var array = new int[elementCount]; + + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdInt32Array_GetData(pArray), array, 0, elementCount); + } + + return array; + } + + internal static void CopyFromArray(Ptr pArray, int[] array) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + var elementCount = array?.Length ?? 0; + instance.StdInt32Array_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, instance.StdInt32Array_GetData(pArray), elementCount); + } + }; + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, int[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdInt32Array_New(elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, instance.StdInt32Array_GetData(pArray), elementCount); + } + + return pArray; + } + + #region Nested type: Ptr + + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class StdUInt32Array + { + public static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdUInt32Array_New(elementCount), V8SplitProxyNative.Instance.StdUInt32Array_Delete); + } + + public static IScope CreateScope(uint[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdUInt32Array_Delete); + } + + public static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdUInt32Array_GetElementCount(pArray); + } + + public static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdUInt32Array_SetElementCount(pArray, elementCount); + } + + public static uint[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdUInt32Array_GetElementCount(pArray); + var array = new uint[elementCount]; + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(V8SplitProxyNative.Instance.StdUInt32Array_GetData(pArray), (ulong)elementCount, array, 0); + } + + return array; + } + + public static void CopyFromArray(Ptr pArray, uint[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdUInt32Array_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, V8SplitProxyNative.Instance.StdUInt32Array_GetData(pArray)); + } + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, uint[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdUInt32Array_New(elementCount); + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, instance.StdUInt32Array_GetData(pArray)); + } + + return pArray; + } + + #region Nested type: Ptr + + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class StdUInt64Array + { + public static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdUInt64Array_New(elementCount), V8SplitProxyNative.Instance.StdUInt64Array_Delete); + } + + public static IScope CreateScope(ulong[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdUInt64Array_Delete); + } + + public static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdUInt64Array_GetElementCount(pArray); + } + + public static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdUInt64Array_SetElementCount(pArray, elementCount); + } + + public static ulong[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdUInt64Array_GetElementCount(pArray); + var array = new ulong[elementCount]; + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(V8SplitProxyNative.Instance.StdUInt64Array_GetData(pArray), (ulong)elementCount, array, 0); + } + + return array; + } + + public static void CopyFromArray(Ptr pArray, ulong[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdUInt64Array_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, V8SplitProxyNative.Instance.StdUInt64Array_GetData(pArray)); + } + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, ulong[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdUInt64Array_New(elementCount); + + if (elementCount > 0) + { + UnmanagedMemoryHelpers.Copy(array, 0, (ulong)elementCount, instance.StdUInt64Array_GetData(pArray)); + } + + return pArray; + } + + #region Nested type: Ptr + + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class StdPtrArray + { + public static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdPtrArray_New(elementCount), V8SplitProxyNative.Instance.StdPtrArray_Delete); + } + + public static IScope CreateScope(IntPtr[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), V8SplitProxyNative.Instance.StdPtrArray_Delete); + } + + public static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdPtrArray_GetElementCount(pArray); + } + + public static void SetElementCount(Ptr pArray, int elementCount) + { + V8SplitProxyNative.Instance.StdPtrArray_SetElementCount(pArray, elementCount); + } + + public static IntPtr[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdPtrArray_GetElementCount(pArray); + var array = new IntPtr[elementCount]; + + if (elementCount > 0) + { + Marshal.Copy(V8SplitProxyNative.Instance.StdPtrArray_GetData(pArray), array, 0, elementCount); + } + + return array; + } + + public static void CopyFromArray(Ptr pArray, IntPtr[] array) + { + var elementCount = array?.Length ?? 0; + V8SplitProxyNative.Instance.StdPtrArray_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, V8SplitProxyNative.Instance.StdPtrArray_GetData(pArray), elementCount); + } + } + + private static Ptr NewFromArray(IV8SplitProxyNative instance, IntPtr[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdPtrArray_New(elementCount); + + if (elementCount > 0) + { + Marshal.Copy(array, 0, instance.StdPtrArray_GetData(pArray), elementCount); + } + + return pArray; + } + + #region Nested type: Ptr + + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + /// + /// Wraps an std::vector<V8Value>. + /// + public readonly ref struct StdV8ValueArray + { + internal readonly Ptr ptr; + private readonly V8Value.Ptr data; + private readonly bool owns; + + /// + /// Create a new std::vector<V8Value> of a given length. + /// + /// The length of the new std::vector<V8Value>. + public StdV8ValueArray(int elementCount) + { + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + ptr = V8SplitProxyNative.Instance.StdV8ValueArray_New(elementCount); + data = V8SplitProxyNative.Instance.StdV8ValueArray_GetData(ptr); + owns = true; + } + + internal StdV8ValueArray(Ptr pArray) + { + ptr = pArray; + owns = false; + + data = pArray != Ptr.Null + ? V8SplitProxyNative.Instance.StdV8ValueArray_GetData(ptr) : V8Value.Ptr.Null; + } + + /// + /// Delete the wrapped std::vector<V8Value>. + /// + public void Dispose() + { + if (owns) + { + Ptr ptr = this.ptr; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + } + } + + /// + /// Retrieve an element of the wrapped std::vector<V8Value>. + /// + /// The index of the element to retrieve. + /// The element. + public V8Value this[int index] + { + get + { + if (ptr == Ptr.Null) + throw new NullReferenceException("StdV8ValueArray is uninitialized"); + + return new V8Value(GetElementPtr(data, index)); + } + } + + internal static IScope CreateScope(int elementCount = 0) + { + return Scope.Create(() => V8SplitProxyNative.Instance.StdV8ValueArray_New(elementCount), ptr => + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + }); + } + + internal static IScope CreateScope(object[] array) + { + return Scope.Create(() => NewFromArray(V8SplitProxyNative.Instance, array), ptr => + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_Delete(ptr); + }); + } + + internal static int GetElementCount(Ptr pArray) + { + return V8SplitProxyNative.Instance.StdV8ValueArray_GetElementCount(pArray); + } + + internal static void SetElementCount(Ptr pArray, int elementCount) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + internal static object[] ToArray(Ptr pArray) + { + var elementCount = V8SplitProxyNative.Instance.StdV8ValueArray_GetElementCount(pArray); + var array = new object[elementCount]; + + if (elementCount > 0) + { + var pElements = V8SplitProxyNative.Instance.StdV8ValueArray_GetData(pArray); + for (var index = 0; index < elementCount; index++) + { + array[index] = V8Value.Get(GetElementPtr(pElements, index)); + } + } + + return array; + } + + internal static void CopyFromArray(Ptr pArray, object[] array) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + var elementCount = array?.Length ?? 0; + instance.StdV8ValueArray_SetElementCount(pArray, elementCount); + + if (elementCount > 0) + { + var pElements = instance.StdV8ValueArray_GetData(pArray); + for (var index = 0; index < elementCount; index++) + { + V8Value.Set(GetElementPtr(pElements, index), array[index]); + } + } + }; + } + + internal static Ptr NewFromArray(IV8SplitProxyNative instance, object[] array) + { + var elementCount = array?.Length ?? 0; + var pArray = instance.StdV8ValueArray_New(elementCount); + + var pData = instance.StdV8ValueArray_GetData(pArray); + for (var index = 0; index < elementCount; index++) + { + V8Value.Set(GetElementPtr(pData, index), array[index]); + } + + return pArray; + } + + internal static V8Value.Ptr GetElementPtr(V8Value.Ptr pV8Value, int index) + { + return (V8Value.Ptr)((IntPtr)pV8Value + index * V8Value.Size); + } + + #region Nested type: Ptr + + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + /// + /// Wraps a V8Value. + /// + public readonly ref struct V8Value + { + internal readonly Ptr ptr; + private readonly bool owns; + + /// + /// Create a new value. + /// + /// + public static V8Value New() + { + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + Ptr ptr = V8SplitProxyNative.Instance.V8Value_New(); + return new V8Value(ptr, true); + } + + internal V8Value(Ptr pValue) : this(pValue, false) { } + + private V8Value(Ptr pValue, bool owns) + { + ptr = pValue; + this.owns = owns; + } + + /// + /// Delete the wrapped V8Value. + /// + public void Dispose() + { + if (owns) + { + Ptr ptr = this.ptr; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_Delete(ptr); + } + } + + /// + /// Retrieve the value of the wrapped V8Value. + /// + /// A variant struct that holds a copy of the contents of the wrapped V8Value. + /// + /// If the retrieved value is a , it is your responsibility to + /// dispose of it by calling on it. + /// + public Decoded Decode() + { + Ptr ptr = this.ptr; + + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Value_Decode(ptr, out Decoded decoded); + return decoded; + }; + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public BigInteger GetBigInt() + { + using var decoded = Decode(); + return decoded.GetBigInt(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public bool GetBoolean() + { + using var decoded = Decode(); + return decoded.GetBoolean(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public DateTime GetDateTime() + { + using var decoded = Decode(); + return decoded.GetDateTime(); + } + + /// + /// Decode the value and attempt to obtain a host object from it. + /// + /// The host object value. + public object GetHostObject() + { + using var decoded = Decode(); + return decoded.GetHostObject(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public int GetInt32() + { + using var decoded = Decode(); + return decoded.GetInt32(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public double GetNumber() + { + using var decoded = Decode(); + return decoded.GetNumber(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public string GetString() + { + using var decoded = Decode(); + return decoded.GetString(); + } + + /// + /// Decode the value and attempt to obtain a from it. + /// + /// The value. + public uint GetUInt32() + { + using var decoded = Decode(); + return decoded.GetUInt32(); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetBigInt(BigInteger value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetBigInt(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetBoolean(bool value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetBoolean(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetDateTime(DateTime value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetDateTime(ptr, value); + } + + /// + /// Store a pointer to a host object in the wrapped V8Value as a + /// or . + /// + /// The pointer to store. + /// + /// For best performance, only pass IV8HostObject or InvokeHostObject to JavaScript. + /// + public void SetHostObject(object value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + if (value != null) + SetHostObject(ptr, value); + else + SetNull(ptr); + } + + /// + /// Store an in the wrapped V8Value as a . + /// + /// The value to store. + public void SetInt32(int value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a (nothing, not even null, not even undefined) in the wrapped + /// V8Value as a . Nonexistent is the default value of V8Value. + /// + public void SetNonexistent() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNonexistent(ptr); + } + + /// + /// Store a null in the wrapped V8Value as a . + /// + public void SetNull() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNull(ptr); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetNumber(double value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a in the wrapped V8Value as a or + /// . + /// + /// The value to store. + public void SetString(string value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + if (value != null) + SetString(ptr, value); + else + SetNull(ptr); + } + + /// + /// Store an in the wrapped V8Value as a . + /// + public void SetUndefined() + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetUndefined(ptr); + } + + /// + /// Store a in the wrapped V8Value as a . + /// + /// The value to store. + public void SetUInt32(uint value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + SetNumeric(ptr, value); + } + + /// + /// Store a JavaScript object in the wrapped V8Value as a . + /// + /// The value to store. + public void SetV8Object(ScriptObject value) + { + if (ptr == Ptr.Null) + throw new NullReferenceException("V8Value is uninitialized"); + + var impl = ((V8ScriptItem)value).Unwrap(); + SetV8Object(ptr, (V8ObjectImpl)impl); + } + + internal const int Size = 16; + + internal static IScope CreateScope() + { + return Scope.Create(() => V8SplitProxyNative.Instance.V8Value_New(), ptr => + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_Delete(ptr); + }); + } + + internal static IScope CreateScope(object obj) + { + var scope = CreateScope(); + Set(scope.Value, obj); + return scope; + } + + internal static void Set(Ptr pV8Value, object obj) + { + if (obj is Nonexistent) + { + SetNonexistent(pV8Value); + return; + } + + if (obj == null) + { + SetUndefined(pV8Value); + return; + } + + if (obj is DBNull) + { + SetNull(pV8Value); + return; + } + + { + if (obj is bool value) + { + SetBoolean(pV8Value, value); + return; + } + } + + { + if (obj is char value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is sbyte value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is byte value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is short value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is ushort value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is int value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is uint value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is long value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is ulong value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is float value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is double value) + { + SetNumeric(pV8Value, value); + return; + } + } + + { + if (obj is decimal value) + { + SetNumeric(pV8Value, (double)value); + return; + } + } + + { + if (obj is string value) + { + SetString(pV8Value, value); + return; + } + } + + { + if (obj is DateTime value) + { + SetDateTime(pV8Value, value); + return; + } + } + + { + if (obj is BigInteger value) + { + SetBigInt(pV8Value, value); + return; + } + } + + { + if (obj is V8ObjectImpl v8ObjectImpl) + { + SetV8Object(pV8Value, v8ObjectImpl); + return; + } + } + + SetHostObject(pV8Value, obj); + } + + internal static object Get(Ptr pV8Value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Value_Decode(pV8Value, out Decoded decoded); + return decoded.Get(); + } + } + + private static bool TryGetBigInteger(int signBit, int wordCount, IntPtr pWords, out BigInteger result) + { + result = BigInteger.Zero; + + if (wordCount > 0) + { + var byteCount = (ulong)wordCount * sizeof(ulong); + if (byteCount >= int.MaxValue) + { + return false; + } + + // use extra zero byte to force unsigned interpretation + var bytes = new byte[byteCount + 1]; + UnmanagedMemoryHelpers.Copy(pWords, byteCount, bytes, 0); + + // construct result and negate if necessary + result = new BigInteger(bytes); + if (signBit != 0) + { + result = BigInteger.Negate(result); + } + } + + return true; + } + + private static void SetNonexistent(Ptr pV8Value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNonexistent(pV8Value); + } + + private static void SetUndefined(Ptr pV8Value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetUndefined(pV8Value); + } + + private static void SetNull(Ptr pV8Value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNull(pV8Value); + } + + private static void SetBoolean(Ptr pV8Value, bool value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetBoolean(pV8Value, value); + } + + private static void SetNumeric(Ptr pV8Value, double value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetNumber(pV8Value, value); + } + + private static void SetNumeric(Ptr pV8Value, int value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetInt32(pV8Value, value); + } + + private static void SetNumeric(Ptr pV8Value, uint value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetUInt32(pV8Value, value); + } + + private static void SetString(Ptr pV8Value, string value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetString(pV8Value, value); + } + + private static void SetDateTime(Ptr pV8Value, DateTime value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetDateTime(pV8Value, (value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds); + } + + private static void SetBigInt(Ptr pV8Value, BigInteger value) + { + var signBit = 0; + if (value.Sign < 0) + { + signBit = 1; + value = BigInteger.Negate(value); + } + + var bytes = value.ToByteArray(); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetBigInt(pV8Value, signBit, bytes); + } + + private static void SetV8Object(Ptr pV8Value, V8ObjectImpl v8ObjectImpl) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetV8Object(pV8Value, v8ObjectImpl.Handle, v8ObjectImpl.Subtype, v8ObjectImpl.Flags); + } + + private static void SetHostObject(Ptr pV8Value, object obj) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Value_SetHostObject(pV8Value, V8ProxyHelpers.AddRefHostObject(obj)); + } + + #region Nested type: Type + + /// + /// The type of the wrapped V8Value. + /// + public enum Type : byte + { + // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Type + + /// + /// . This is the default value of V8Value. + /// + Nonexistent, + + /// + /// Returned by JavaScript when a property does not exist. + /// + Undefined, + + /// + /// An untyped null. + /// + Null, + + /// + /// . + /// + Boolean, + + /// + /// . + /// + Number, + + /// + /// . + /// + Int32, + + /// + /// . + /// + UInt32, + + /// + /// . + /// + String, + + /// + /// . + /// + DateTime, + + /// + /// . + /// + BigInt, + + /// + /// A JavaScript object. + /// + V8Object, + + /// + /// A host object. + /// + HostObject + } + + #endregion + + #region Nested type: Subtype + + /// + /// If the wrapped V8Value is a , what kind of object it is. + /// + public enum Subtype : byte + { + // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Subtype + + /// + /// A regular JavaScript object. + /// + None, + + /// + /// A function. + /// + Function, + + /// + /// An iterator. + /// + Iterator, + + /// + /// A promise. + /// + Promise, + + /// + /// An array of JavaScript objects. + /// + Array, + + /// + /// An array buffer. + /// + ArrayBuffer, + + /// + /// A data view. + /// + DataView, + + /// + /// An array of . + /// + Uint8Array, + + /// + /// An array of . + /// + Uint8ClampedArray, + + /// + /// A array of . + /// + Int8Array, + + /// + /// A array of . + /// + Uint16Array, + + /// + /// An array of . + /// + Int16Array, + + /// + /// An array of . + /// + Uint32Array, + + /// + /// An array of . + /// + Int32Array, + + /// + /// An array of . + /// + BigUint64Array, + + /// + /// An array of . + /// + BigInt64Array, + + /// + /// An array of . + /// + Float32Array, + + /// + /// An array of . + /// + Float64Array + } + + #endregion + + #region Nested type: Flags + + /// + /// If the wrapped V8Value is a , additional information about it. + /// + [Flags] + public enum Flags : ushort + { + // IMPORTANT: maintain bitwise equivalence with native enum V8Value::Flags + + /// + /// No special meaning. + /// + None = 0, + + /// + /// If the object is shared between something, I don't know. + /// + Shared = 0x0001, + + /// + /// If the wrapped V8Value is a , if it's async. + /// + Async = 0x0002, + + /// + /// If thewrapped V8Value is a , if it's a generator (contains + /// yield statements). + /// + Generator = 0x0004 + } + + #endregion + + #region Nested type: Ptr + + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + + #region Nested type: Decoded + + /// + /// A variant struct that contains the value retrieved from a . + /// + [StructLayout(LayoutKind.Explicit)] + public struct Decoded : IDisposable + { + // IMPORTANT: maintain bitwise equivalence with native struct V8Value::Decoded + + /// + /// The type of the value. + /// + [FieldOffset(0)] public Type Type; + + /// + /// If the value is a , what kind of object it is. + /// + [FieldOffset(1)] public Subtype Subtype; + + /// + /// If the value is a , additional information about it. + /// + [FieldOffset(2)] public Flags Flags; + + /// + /// If the value is a , if it's negative. + /// + [FieldOffset(2)] public short SignBit; + + /// + /// If the value is a or a , how long it + /// is. + /// + [FieldOffset(4)] public int Length; + + /// + /// If the value is a pointer to a , the object's identity hash. + /// + [FieldOffset(4)] public int IdentityHash; + + /// + /// If the value is a , its value. + /// + [FieldOffset(8)] public int Int32Value; + + /// + /// If the value is a , its value. + /// + [FieldOffset(8)] public uint UInt32Value; + + /// + /// If the value is a , its value. + /// + [FieldOffset(8)] public double DoubleValue; + + /// + /// If the value is a or a , + /// pointer to it. + /// + [FieldOffset(8)] public IntPtr PtrOrHandle; + + /// + /// If the value is a , we must dispose of it when we're done. + /// + public void Dispose() + { + if (Type == Type.V8Object) + { + Type = Type.Nonexistent; + var hEntity = (V8Entity.Handle)PtrOrHandle; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8Entity_DestroyHandle(hEntity); + } + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a + /// If the value is not a . + /// If the big integer is more than two gigabytes in size. + public readonly BigInteger GetBigInt() + { + if (Type != Type.BigInt) + throw new InvalidCastException($"Tried to get a BigInt out of a {GetTypeName()}"); + + if (!TryGetBigInteger(SignBit, Length, PtrOrHandle, out var result)) + throw new NotSupportedException("The size of the big integer exceeds two gigabytes"); + + return result; + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a . + /// If the value is not a . + public readonly bool GetBoolean() + { + if (Type != Type.Boolean) + throw new InvalidCastException($"Tried to get a Boolean out of a {GetTypeName()}"); + + return Int32Value != 0; + } + + /// + /// Chech that the value is a and return it as a + /// . + /// + /// The value as a . + /// + /// The must have been created with the + /// flag set for this method to + /// work. Else, the Date object will be passed from JavaScript as a + /// . + /// + public readonly DateTime GetDateTime() + { + if (Type != Type.DateTime) + throw new InvalidCastException($"Tried to get a DateTime out of a {GetTypeName()}"); + + return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) + + TimeSpan.FromMilliseconds(DoubleValue); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value as a . + /// If the value is not a . + public readonly double GetNumber() + { + if (Type != Type.Number) + throw new InvalidCastException($"Tried to get a Double out of a {GetTypeName()}"); + + return DoubleValue; + } + + /// + /// Check that the value is a pointer to a and return it as an + /// . + /// + /// The pointer as an . + /// If the value is not a . + public readonly object GetHostObject() + { + if (Type != Type.HostObject) + throw new InvalidCastException($"Tried to get a host object out of a {GetTypeName()}"); + + return V8ProxyHelpers.GetHostObject(PtrOrHandle); + } + + /// + /// Check that the value is a and return it as an + /// . + /// + /// The value as an . + /// If the value is not a . + public readonly int GetInt32() + { + if (Type != Type.Int32) + throw new InvalidCastException($"Tried to get an Int32 out of a {GetTypeName()}"); + + return Int32Value; + } + + /// + /// Check that the value is a and return a + /// that wraps it. + /// + /// The pointer to the wrapped in a . + /// The value is not a pointer to a . + public readonly V8Object GetV8Object() + { + if (Type != Type.V8Object) + throw new InvalidCastException($"Tried to get a JavaScript object out of a {GetTypeName()}"); + + return new V8Object((V8Object.Handle)PtrOrHandle, IdentityHash); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value decoded as a . + /// If the value is not a . + public readonly string GetString() + { + if (Type != Type.String) + throw new InvalidCastException($"Tried to get a String out of a {GetTypeName()}"); + + return Marshal.PtrToStringUni(PtrOrHandle, Length); + } + + /// + /// Check that the value is a and return it as a + /// . + /// + /// The value decoded as a . + /// If the value is not a . + public readonly uint GetUInt32() + { + if (Type != Type.UInt32) + throw new InvalidCastException($"Tried to get a UInt32 out of a {GetTypeName()}"); + + return UInt32Value; + } + + /// + /// Check that the value is a pointer to and return a + /// that wraps it. + /// + /// The pointer to the wrapped in a . + /// If the value is not a pointer to a . + public readonly Uint8Array GetUint8Array() + { + if (Type != Type.V8Object || Subtype != Subtype.Uint8Array) + throw new InvalidCastException( + $"Tried to get a Uint8Array out of a {GetTypeName()}"); + + return new Uint8Array((V8Object.Handle)PtrOrHandle); + } + + /// + /// Return a string describing the type of the value. + /// + /// A string describing the type of the value. + public readonly string GetTypeName() + { + return Type != Type.V8Object || Subtype == Subtype.None + ? Type.ToString() : Subtype.ToString(); + } + + /// + /// Returns a string representing the value and the type of the value. + /// + /// A string representing the value and the type of the value. + public override string ToString() => Type switch + { + Type.Nonexistent => "void (Nonexistent)", + Type.Undefined => "undefined (Undefined)", + Type.Null => "null (Null)", + Type.Boolean => Int32Value != 0 ? "True (Boolean)" : "False (Boolean)", + Type.Number => $"{DoubleValue} (Number)", + Type.Int32 => $"{Int32Value} (Int32)", + Type.UInt32 => $"{UInt32Value} (UInt32)", + Type.String => $"\"{Marshal.PtrToStringUni(PtrOrHandle, Length)}\" (String)", + Type.DateTime => $"{new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) + TimeSpan.FromMilliseconds(DoubleValue)} (DateTime)", + Type.BigInt => $"{(TryGetBigInteger(SignBit, Length, PtrOrHandle, out var bigInt) ? bigInt.ToString() : "null")} (BigInt)", + Type.V8Object => $"0x{PtrOrHandle:x} ({Subtype})", + Type.HostObject => $"0x{PtrOrHandle:x} (HostObject)", + _ => $"unknown ({Type})" + }; + + internal readonly object Get() + { + switch (Type) + { + case Type.Nonexistent: + return Nonexistent.Value; + + case Type.Null: + return DBNull.Value; + + case Type.Boolean: + return Int32Value != 0; + + case Type.Number: + return DoubleValue; + + case Type.Int32: + return Int32Value; + + case Type.UInt32: + return UInt32Value; + + case Type.String: + return Marshal.PtrToStringUni(PtrOrHandle, Length); + + case Type.DateTime: + return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) + TimeSpan.FromMilliseconds(DoubleValue); + + case Type.BigInt: + return TryGetBigInteger(SignBit, Length, PtrOrHandle, out var result) ? (object)result : null; + + case Type.V8Object: + return new V8ObjectImpl((V8Object.Handle)PtrOrHandle, Subtype, Flags, IdentityHash); + + case Type.HostObject: + return V8ProxyHelpers.GetHostObject(PtrOrHandle); + + default: + return null; + } + } + + internal static unsafe object Get(Ptr pValues, int index) + { + return ((Decoded*)(IntPtr)pValues + index)->Get(); + } + + internal static object[] ToArray(int count, Ptr pValues) + { + var array = new object[count]; + + for (var index = 0; index < count; index++) + { + array[index] = Get(pValues, index); + } + + return array; + } + + #region Nested type: Ptr + + // ReSharper disable once MemberHidesStaticFromOuterClass + internal readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + #endregion + } + + internal static class V8CpuProfile + { + public static void ProcessProfile(V8Entity.Handle hEntity, Ptr pProfile, V8.V8CpuProfile profile) + { + string name = null; + var startTimestamp = 0UL; + var endTimestamp = 0UL; + var sampleCount = 0; + var pRootNode = Node.Ptr.Null; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8CpuProfile_GetInfo(pProfile, hEntity, out name, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + + profile.Name = name; + profile.StartTimestamp = startTimestamp; + profile.EndTimestamp = endTimestamp; + + if (pRootNode != Node.Ptr.Null) + { + profile.RootNode = CreateNode(hEntity, pRootNode); + } + + if (sampleCount > 0) + { + var samples = new List(sampleCount); + + for (var index = 0; index < sampleCount; index++) + { + var nodeId = 0UL; + var timestamp = 0UL; + var sampleIndex = index; + bool found; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + found = instance.V8CpuProfile_GetSample(pProfile, sampleIndex, out nodeId, out timestamp); + + if (found) + { + var node = profile.FindNode(nodeId); + if (node != null) + { + samples.Add(new V8.V8CpuProfile.Sample { Node = node, Timestamp = timestamp }); + } + } + } + + if (samples.Count > 0) + { + profile.Samples = new ReadOnlyCollection(samples); + } + } + } + + private static V8.V8CpuProfile.Node CreateNode(V8Entity.Handle hEntity, Node.Ptr pNode) + { + var nodeId = 0UL; + var scriptId = 0L; + string scriptName = null; + string functionName = null; + string bailoutReason = null; + var lineNumber = 0L; + var columnNumber = 0L; + var hitCount = 0UL; + var hitLineCount = 0U; + var childCount = 0; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + instance.V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, out scriptName, out functionName, out bailoutReason, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + + var node = new V8.V8CpuProfile.Node + { + NodeId = nodeId, + ScriptId = scriptId, + ScriptName = scriptName, + FunctionName = functionName, + BailoutReason = bailoutReason, + LineNumber = lineNumber, + ColumnNumber = columnNumber, + HitCount = hitCount, + }; + + if (hitLineCount > 0) + { + int[] lineNumbers = null; + uint[] hitCounts = null; + bool found; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + found = instance.V8CpuProfileNode_GetHitLines(pNode, out lineNumbers, out hitCounts); + + if (found) + { + var actualHitLineCount = Math.Min(lineNumbers.Length, hitCounts.Length); + if (actualHitLineCount > 0) + { + var hitLines = new V8.V8CpuProfile.Node.HitLine[actualHitLineCount]; + + for (var index = 0; index < actualHitLineCount; index++) + { + hitLines[index].LineNumber = lineNumbers[index]; + hitLines[index].HitCount = hitCounts[index]; + } + + node.HitLines = new ReadOnlyCollection(hitLines); + } + } + } + + if (childCount > 0) + { + var childNodes = new List(childCount); + + for (var index = 0; index < childCount; index++) + { + var childIndex = index; + Node.Ptr pChildNode; + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + pChildNode = instance.V8CpuProfileNode_GetChildNode(pNode, childIndex); + + if (pChildNode != Node.Ptr.Null) + { + childNodes.Add(CreateNode(hEntity, pChildNode)); + } + } + + if (childNodes.Count > 0) + { + node.ChildNodes = new ReadOnlyCollection(childNodes); + } + } + + return node; + } + + #region Nested type: Ptr + + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + + #region Nested type: Node + + internal static class Node + { + #region Nested type: Ptr + + // ReSharper disable once MemberHidesStaticFromOuterClass + public readonly struct Ptr + { + private readonly IntPtr bits; + + private Ptr(IntPtr bits) => this.bits = bits; + + public static readonly Ptr Null = new Ptr(IntPtr.Zero); + + public static bool operator ==(Ptr left, Ptr right) => left.bits == right.bits; + public static bool operator !=(Ptr left, Ptr right) => left.bits != right.bits; + + public static explicit operator IntPtr(Ptr ptr) => ptr.bits; + public static explicit operator Ptr(IntPtr bits) => new Ptr(bits); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Ptr ptr) && (this == ptr); + public override int GetHashCode() => bits.GetHashCode(); + + #endregion + } + + #endregion + } + + #endregion + } + + #endregion + + #region V8 entity helpers + + internal static class V8Entity + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class V8Isolate + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class V8Context + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + /// + /// Wraps a JavaScript object. + /// + public readonly ref struct V8Object + { + internal readonly Handle ptr; + private readonly int identityHash; + + internal V8Object(Handle hObject, int identityHash) + { + if (hObject == Handle.Empty) + throw new ArgumentNullException(nameof(hObject)); + + ptr = hObject; + this.identityHash = identityHash; + } + + /// + /// Obtain a thin wrapper around a JavaScript object wrapped by a . + /// + /// A wrapper around a JavaScript object. + /// + /// The common case is to pass to this constructor. + /// + public V8Object(ScriptObject scriptObject) + { + if (ScriptEngine.Current == null) + throw new InvalidOperationException("You must be inside a script engine scope"); + + object target = ((V8ScriptItem)scriptObject).Unwrap(); + var impl = (V8ObjectImpl)target; + ptr = impl.Handle; + identityHash = impl.IdentityHash; + } + + /// + /// Return the identity hash of the JavaScript object. + /// + /// The identity hash of the JavaScript object. + public override int GetHashCode() + { + return identityHash; + } + + /// + /// Obtain the value of a named property of the wrapped JavaScript object. + /// + /// The name of the property. + /// The value of the property will be written here. + public void GetNamedProperty(StdString name, V8Value value) + { + Handle hObject = ptr; + StdString.Ptr pName = name.ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pName == StdString.Ptr.Null) + throw new ArgumentNullException(nameof(name)); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetNamedProperty(hObject, pName, pValue); + } + + /// + /// Obtain the value of a named property of the wrapped JavaScript object. + /// + /// The name of the property. + /// The value of the property will be written here. + public void GetNamedProperty(string name, V8Value value) + { + Handle hObject = ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (name == null) + throw new ArgumentNullException(nameof(name)); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using var stdName = new StdString(name); + StdString.Ptr pName = stdName.ptr; + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetNamedProperty(hObject, pName, pValue); + } + + /// + /// Obtain the value of an indexed property of the wrapped JavaScript object. + /// + /// The index of the property. + /// The value of the property will be written here. + public void GetIndexedProperty(int index, V8Value value) + { + Handle hObject = ptr; + V8Value.Ptr pValue = value.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pValue == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(value)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_GetIndexedProperty(hObject, index, pValue); + } + + /// + /// Invoke the wrapped JavaScript object as a function. + /// + /// The arguments to pass to the function. + /// The return value of the function will be written here. + /// Call the JavaScript as a constructor? + public void Invoke(StdV8ValueArray args, V8Value result, bool asConstructor = false) + { + Handle hObject = ptr; + StdV8ValueArray.Ptr pArgs = args.ptr; + V8Value.Ptr pResult = result.ptr; + + if (hObject == Handle.Empty) + throw new NullReferenceException("V8Object is uninitialized"); + + if (pArgs == StdV8ValueArray.Ptr.Null) + throw new ArgumentNullException(nameof(args)); + + if (pResult == V8Value.Ptr.Null) + throw new ArgumentNullException(nameof(result)); + + using (V8SplitProxyNative.Invoke(out var instance)) + instance.V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + #region Nested type: Handle + + internal readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class V8Script + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class V8DebugCallback + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + internal static class NativeCallback + { + #region Nested type: Handle + + public readonly struct Handle + { + private readonly IntPtr guts; + + private Handle(IntPtr guts) => this.guts = guts; + + public static readonly Handle Empty = new Handle(IntPtr.Zero); + + public static bool operator ==(Handle left, Handle right) => left.guts == right.guts; + public static bool operator !=(Handle left, Handle right) => left.guts != right.guts; + + public static explicit operator IntPtr(Handle handle) => handle.guts; + public static explicit operator Handle(IntPtr guts) => new Handle(guts); + + public static implicit operator V8Entity.Handle(Handle handle) => (V8Entity.Handle)handle.guts; + public static explicit operator Handle(V8Entity.Handle handle) => (Handle)(IntPtr)handle; + + #region Object overrides + + public override bool Equals(object obj) => (obj is Handle handle) && (this == handle); + public override int GetHashCode() => guts.GetHashCode(); + + #endregion + } + + #endregion + } + + #endregion +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs.meta new file mode 100644 index 000000000..4bb1012e9 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f7462fade00370429de20ebc988f1c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs new file mode 100644 index 000000000..a59e26df1 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs @@ -0,0 +1,1172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + // ReSharper disable once PartialTypeWithSinglePart + internal static partial class V8SplitProxyManaged + { + public static IntPtr MethodTable => pFunctionPtrs; + + private static IntPtr pDelegatePtrs; + private static IntPtr pFunctionPtrs; + private static int methodCount; + + [ThreadStatic] public static Exception ScheduledException; + + public static void Initialize() + { + CreateMethodTable(); + } + + public static void Teardown() + { + DestroyMethodTable(); + } + + private static void ScheduleHostException(IntPtr pObject, Exception exception) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.HostException_Schedule(exception.GetBaseException().Message, V8ProxyHelpers.MarshalExceptionToScript(pObject, exception)); + } + } + + private static void ScheduleHostException(Exception exception) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.HostException_Schedule(exception.GetBaseException().Message, ScriptEngine.Current?.MarshalToScript(exception)); + } + } + + private static uint GetMaxCacheSizeForCategory(DocumentCategory category) + { + return Math.Max(16U, category.MaxCacheSize); + } + + #region method delegates + + // ReSharper disable UnusedType.Local + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawScheduleForwardingException( + [In] V8Value.Ptr pException + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawScheduleInvalidOperationException( + [In] StdString.Ptr pMessage + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawScheduleScriptEngineException( + [In] StdString.Ptr pEngineName, + [In] StdString.Ptr pMessage, + [In] StdString.Ptr pStackTrace, + [In] [MarshalAs(UnmanagedType.I1)] bool isFatal, + [In] [MarshalAs(UnmanagedType.I1)] bool executionStarted, + [In] V8Value.Ptr pScriptException, + [In] V8Value.Ptr pInnerException + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawScheduleScriptInterruptedException( + [In] StdString.Ptr pEngineName, + [In] StdString.Ptr pMessage, + [In] StdString.Ptr pStackTrace, + [In] [MarshalAs(UnmanagedType.I1)] bool isFatal, + [In] [MarshalAs(UnmanagedType.I1)] bool executionStarted, + [In] V8Value.Ptr pScriptException, + [In] V8Value.Ptr pInnerException + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawInvokeAction( + [In] IntPtr pAction + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawProcessArrayBufferOrViewData( + [In] IntPtr pData, + [In] IntPtr pAction + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawProcessCpuProfile( + [In] V8CpuProfile.Ptr pProfile, + [In] IntPtr pAction + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr RawCreateV8ObjectCache(); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawCacheV8Object( + [In] IntPtr pCache, + [In] IntPtr pObject, + [In] IntPtr pV8Object + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr RawGetCachedV8Object( + [In] IntPtr pCache, + [In] IntPtr pObject + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetAllCachedV8Objects( + [In] IntPtr pCache, + [In] StdPtrArray.Ptr pV8ObjectPtrs + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private delegate bool RawRemoveV8ObjectCacheEntry( + [In] IntPtr pCache, + [In] IntPtr pObject + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr RawCreateDebugAgent( + [In] StdString.Ptr pName, + [In] StdString.Ptr pVersion, + [In] int port, + [In] [MarshalAs(UnmanagedType.I1)] bool remote, + [In] V8DebugCallback.Handle hCallback + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawSendDebugMessage( + [In] IntPtr pAgent, + [In] StdString.Ptr pContent + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawDestroyDebugAgent( + [In] IntPtr pAgent + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate uint RawGetMaxScriptCacheSize(); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate uint RawGetMaxModuleCacheSize(); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr RawAddRefHostObject( + [In] IntPtr pObject + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawReleaseHostObject( + [In] IntPtr pObject + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate Invocability RawGetHostObjectInvocability( + [In] IntPtr pObject + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectNamedProperty( + [In] IntPtr pObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectNamedPropertyWithCacheability( + [In] IntPtr pObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [Out] [MarshalAs(UnmanagedType.I1)] out bool isCacheable + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawSetHostObjectNamedProperty( + [In] IntPtr pObject, + [In] StdString.Ptr pName, + [In] V8Value.Decoded.Ptr pValue + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private delegate bool RawDeleteHostObjectNamedProperty( + [In] IntPtr pObject, + [In] StdString.Ptr pName + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectPropertyNames( + [In] IntPtr pObject, + [In] StdStringArray.Ptr pNames + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectIndexedProperty( + [In] IntPtr pObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawSetHostObjectIndexedProperty( + [In] IntPtr pObject, + [In] int index, + V8Value.Decoded.Ptr pValue + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private delegate bool RawDeleteHostObjectIndexedProperty( + [In] IntPtr pObject, + [In] int index + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectPropertyIndices( + [In] IntPtr pObject, + [In] StdInt32Array.Ptr pIndices + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawInvokeHostObject( + [In] IntPtr pObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] int argCount, + [In] V8Value.Decoded.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawInvokeHostObjectMethod( + [In] IntPtr pObject, + [In] StdString.Ptr pName, + [In] int argCount, + [In] V8Value.Decoded.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectEnumerator( + [In] IntPtr pObject, + [In] V8Value.Ptr pResult + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawGetHostObjectAsyncEnumerator( + [In] IntPtr pObject, + [In] V8Value.Ptr pResult + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawQueueNativeCallback( + [In] NativeCallback.Handle hCallback + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr RawCreateNativeCallbackTimer( + [In] int dueTime, + [In] int period, + [In] NativeCallback.Handle hCallback + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private delegate bool RawChangeNativeCallbackTimer( + [In] IntPtr pTimer, + [In] int dueTime, + [In] int period + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawDestroyNativeCallbackTimer( + [In] IntPtr pTimer + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawLoadModule( + [In] IntPtr pSourceDocumentInfo, + [In] StdString.Ptr pSpecifier, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [Out] out ulong uniqueId, + [Out] out DocumentKind documentKind, + [In] StdString.Ptr pCode, + [Out] out IntPtr pDocumentInfo, + [In] V8Value.Ptr pExports + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawCreateModuleContext( + [In] IntPtr pDocumentInfo, + [In] StdStringArray.Ptr pNames, + [In] StdV8ValueArray.Ptr pValues + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void RawWriteBytesToStream( + [In] IntPtr pStream, + [In] IntPtr pBytes, + [In] int count + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate V8GlobalFlags RawGetGlobalFlags(); + + // ReSharper restore UnusedType.Local + + #endregion + + #region method table construction and teardown + + private static void CreateMethodTable() + { + Debug.Assert(methodCount == 0); + + (IntPtr, IntPtr)[] methodPairs = + { + //---------------------------------------------------------------------------- + // IMPORTANT: maintain synchronization with V8_SPLIT_PROXY_MANAGED_METHOD_LIST + //---------------------------------------------------------------------------- + + GetMethodPair(ScheduleForwardingException), + GetMethodPair(ScheduleInvalidOperationException), + GetMethodPair(ScheduleScriptEngineException), + GetMethodPair(ScheduleScriptInterruptedException), + + #if NET5_0_OR_GREATER + (IntPtr.Zero, InvokeHostActionFastMethodPtr), + #else + GetMethodPair(InvokeHostAction), + #endif + + GetMethodPair(ProcessArrayBufferOrViewData), + GetMethodPair(ProcessCpuProfile), + GetMethodPair(CreateV8ObjectCache), + + #if NET5_0_OR_GREATER + (IntPtr.Zero, CacheV8ObjectFastMethodPtr), + (IntPtr.Zero, GetCachedV8ObjectFastMethodPtr), + #else + GetMethodPair(CacheV8Object), + GetMethodPair(GetCachedV8Object), + #endif + + GetMethodPair(GetAllCachedV8Objects), + GetMethodPair(RemoveV8ObjectCacheEntry), + GetMethodPair(CreateDebugAgent), + GetMethodPair(SendDebugMessage), + GetMethodPair(DestroyDebugAgent), + GetMethodPair(GetMaxScriptCacheSize), + GetMethodPair(GetMaxModuleCacheSize), + + #if NET5_0_OR_GREATER + (IntPtr.Zero, AddRefHostObjectFastMethodPtr), + (IntPtr.Zero, ReleaseHostObjectFastMethodPtr), + (IntPtr.Zero, GetHostObjectInvocabilityFastMethodPtr), + #else + GetMethodPair(AddRefHostObject), + GetMethodPair(ReleaseHostObject), + GetMethodPair(GetHostObjectInvocability), + #endif + + #if NET5_0_OR_GREATER + (IntPtr.Zero, GetHostObjectNamedPropertyFastMethodPtr), + (IntPtr.Zero, GetHostObjectNamedPropertyWithCacheabilityFastMethodPtr), + (IntPtr.Zero, SetHostObjectNamedPropertyFastMethodPtr), + #else + GetMethodPair(GetHostObjectNamedProperty), + GetMethodPair(GetHostObjectNamedPropertyWithCacheability), + GetMethodPair(SetHostObjectNamedProperty), + #endif + + GetMethodPair(DeleteHostObjectNamedProperty), + GetMethodPair(GetHostObjectPropertyNames), + + #if NET5_0_OR_GREATER + (IntPtr.Zero, GetHostObjectIndexedPropertyFastMethodPtr), + (IntPtr.Zero, SetHostObjectIndexedPropertyFastMethodPtr), + #else + GetMethodPair(GetHostObjectIndexedProperty), + GetMethodPair(SetHostObjectIndexedProperty), + #endif + + GetMethodPair(DeleteHostObjectIndexedProperty), + GetMethodPair(GetHostObjectPropertyIndices), + + #if NET5_0_OR_GREATER + (IntPtr.Zero, InvokeHostObjectFastMethodPtr), + (IntPtr.Zero, InvokeHostObjectMethodFastMethodPtr), + #else + GetMethodPair(InvokeHostObject), + GetMethodPair(InvokeHostObjectMethod), + #endif + + GetMethodPair(GetHostObjectEnumerator), + GetMethodPair(GetHostObjectAsyncEnumerator), + GetMethodPair(QueueNativeCallback), + GetMethodPair(CreateNativeCallbackTimer), + GetMethodPair(ChangeNativeCallbackTimer), + GetMethodPair(DestroyNativeCallbackTimer), + GetMethodPair(LoadModule), + GetMethodPair(CreateModuleContext), + GetMethodPair(WriteBytesToStream), + GetMethodPair(GetGlobalFlags) + }; + + methodCount = methodPairs.Length; + pDelegatePtrs = Marshal.AllocCoTaskMem(methodCount * IntPtr.Size); + pFunctionPtrs = Marshal.AllocCoTaskMem(methodCount * IntPtr.Size); + + for (var index = 0; index < methodCount; index++) + { + var (pDelegate, pFunction) = methodPairs[index]; + Marshal.WriteIntPtr(pDelegatePtrs, index * IntPtr.Size, pDelegate); + Marshal.WriteIntPtr(pFunctionPtrs, index * IntPtr.Size, pFunction); + } + } + + private static void DestroyMethodTable() + { + Debug.Assert(methodCount > 0); + + for (var index = 0; index < methodCount; index++) + { + var pDelegate = Marshal.ReadIntPtr(pDelegatePtrs, index * IntPtr.Size); + if (pDelegate != IntPtr.Zero) + { + V8ProxyHelpers.ReleaseHostObject(pDelegate); + } + } + + Marshal.FreeCoTaskMem(pDelegatePtrs); + Marshal.FreeCoTaskMem(pFunctionPtrs); + + methodCount = 0; + pDelegatePtrs = IntPtr.Zero; + pFunctionPtrs = IntPtr.Zero; + } + + private static (IntPtr, IntPtr) GetMethodPair(T del) + { + return (V8ProxyHelpers.AddRefHostObject(del), Marshal.GetFunctionPointerForDelegate((Delegate)(object)del)); + } + + #endregion + + #region method table implementation + + [AOT.MonoPInvokeCallback(typeof(RawScheduleForwardingException))] + private static void ScheduleForwardingException(V8Value.Ptr pException) + { + Debug.Assert(ScheduledException == null); + + var exception = V8ProxyHelpers.MarshalExceptionToHost(V8Value.Get(pException)); + if (exception is ScriptEngineException scriptEngineException) + { + ScheduledException = new ScriptEngineException(scriptEngineException.EngineName, scriptEngineException.Message, scriptEngineException.ErrorDetails, scriptEngineException.HResult, scriptEngineException.IsFatal, scriptEngineException.ExecutionStarted, scriptEngineException.ScriptExceptionAsObject, scriptEngineException); + } + else if (exception is ScriptInterruptedException scriptInterruptedException) + { + ScheduledException = new ScriptInterruptedException(scriptInterruptedException.EngineName, scriptInterruptedException.Message, scriptInterruptedException.ErrorDetails, scriptInterruptedException.HResult, scriptInterruptedException.IsFatal, scriptInterruptedException.ExecutionStarted, scriptInterruptedException.ScriptExceptionAsObject, scriptInterruptedException); + } + else + { + ScheduledException = exception; + } + } + + [AOT.MonoPInvokeCallback(typeof(RawScheduleInvalidOperationException))] + private static void ScheduleInvalidOperationException(StdString.Ptr pMessage) + { + Debug.Assert(ScheduledException == null); + ScheduledException = new InvalidOperationException(StdString.GetValue(pMessage)); + } + + [AOT.MonoPInvokeCallback(typeof(RawScheduleScriptEngineException))] + private static void ScheduleScriptEngineException(StdString.Ptr pEngineName, StdString.Ptr pMessage, StdString.Ptr pStackTrace, bool isFatal, bool executionStarted, V8Value.Ptr pScriptException, V8Value.Ptr pInnerException) + { + Debug.Assert(ScheduledException == null); + var scriptException = ScriptEngine.Current?.MarshalToHost(V8Value.Get(pScriptException), false); + var innerException = V8ProxyHelpers.MarshalExceptionToHost(V8Value.Get(pInnerException)); + ScheduledException = new ScriptEngineException(StdString.GetValue(pEngineName), StdString.GetValue(pMessage), StdString.GetValue(pStackTrace), 0, isFatal, executionStarted, scriptException, innerException); + } + + [AOT.MonoPInvokeCallback(typeof(RawScheduleScriptInterruptedException))] + private static void ScheduleScriptInterruptedException(StdString.Ptr pEngineName, StdString.Ptr pMessage, StdString.Ptr pStackTrace, bool isFatal, bool executionStarted, V8Value.Ptr pScriptException, V8Value.Ptr pInnerException) + { + Debug.Assert(ScheduledException == null); + var scriptException = ScriptEngine.Current?.MarshalToHost(V8Value.Get(pScriptException), false); + var innerException = V8ProxyHelpers.MarshalExceptionToHost(V8Value.Get(pInnerException)); + ScheduledException = new ScriptInterruptedException(StdString.GetValue(pEngineName), StdString.GetValue(pMessage), StdString.GetValue(pStackTrace), 0, isFatal, executionStarted, scriptException, innerException); + } + + [AOT.MonoPInvokeCallback(typeof(RawInvokeAction))] + private static void InvokeHostAction(IntPtr pAction) + { + try + { + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(); + } + catch (Exception exception) + { + ScheduleHostException(exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawProcessArrayBufferOrViewData))] + private static void ProcessArrayBufferOrViewData(IntPtr pData, IntPtr pAction) + { + try + { + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(pData); + } + catch (Exception exception) + { + ScheduleHostException(exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawProcessCpuProfile))] + private static void ProcessCpuProfile(V8CpuProfile.Ptr pProfile, IntPtr pAction) + { + try + { + object method = V8ProxyHelpers.GetHostObject(pAction); + ((Action)method)(pProfile); + } + catch (Exception exception) + { + ScheduleHostException(exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawCreateV8ObjectCache))] + private static IntPtr CreateV8ObjectCache() + { + return V8ProxyHelpers.AddRefHostObject(new Dictionary()); + } + + [AOT.MonoPInvokeCallback(typeof(RawCacheV8Object))] + private static void CacheV8Object(IntPtr pCache, IntPtr pObject, IntPtr pV8Object) + { + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + ((Dictionary)cache).Add(key, pV8Object); + } + + [AOT.MonoPInvokeCallback(typeof(RawGetCachedV8Object))] + private static IntPtr GetCachedV8Object(IntPtr pCache, IntPtr pObject) + { + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + return ((Dictionary)cache).TryGetValue(key, out IntPtr pV8Object) ? pV8Object : IntPtr.Zero; + } + + [AOT.MonoPInvokeCallback(typeof(RawGetAllCachedV8Objects))] + private static void GetAllCachedV8Objects(IntPtr pCache, StdPtrArray.Ptr pV8ObjectPtrs) + { + object cache = V8ProxyHelpers.GetHostObject(pCache); + StdPtrArray.CopyFromArray(pV8ObjectPtrs, ((Dictionary)cache).Values.ToArray()); + } + + [AOT.MonoPInvokeCallback(typeof(RawRemoveV8ObjectCacheEntry))] + private static bool RemoveV8ObjectCacheEntry(IntPtr pCache, IntPtr pObject) + { + object cache = V8ProxyHelpers.GetHostObject(pCache); + object key = V8ProxyHelpers.GetHostObject(pObject); + return ((Dictionary)cache).Remove(key); + } + + [AOT.MonoPInvokeCallback(typeof(RawCreateDebugAgent))] + private static IntPtr CreateDebugAgent(StdString.Ptr pName, StdString.Ptr pVersion, int port, bool remote, V8DebugCallback.Handle hCallback) + { + string name = StdString.GetValue(pName); + string version = StdString.GetValue(pVersion); + IV8DebugListener listener = new V8DebugListenerImpl(hCallback); + V8DebugAgent agent = new V8DebugAgent(name, version, port, remote, listener); + return V8ProxyHelpers.AddRefHostObject(agent); + } + + [AOT.MonoPInvokeCallback(typeof(RawSendDebugMessage))] + private static void SendDebugMessage(IntPtr pAgent, StdString.Ptr pContent) + { + object agent = V8ProxyHelpers.GetHostObject(pAgent); + string content = StdString.GetValue(pContent); + ((V8DebugAgent)agent).SendMessage(content); + } + + [AOT.MonoPInvokeCallback(typeof(RawDestroyDebugAgent))] + private static void DestroyDebugAgent(IntPtr pAgent) + { + object agent = V8ProxyHelpers.GetHostObject(pAgent); + ((V8DebugAgent)agent).Dispose(); + V8ProxyHelpers.ReleaseHostObject(pAgent); + } + + [AOT.MonoPInvokeCallback(typeof(RawGetMaxScriptCacheSize))] + private static uint GetMaxScriptCacheSize() + { + return GetMaxCacheSizeForCategory(DocumentCategory.Script); + } + + [AOT.MonoPInvokeCallback(typeof(RawGetMaxModuleCacheSize))] + private static uint GetMaxModuleCacheSize() + { + return GetMaxCacheSizeForCategory(ModuleCategory.Standard); + } + + [AOT.MonoPInvokeCallback(typeof(RawAddRefHostObject))] + private static IntPtr AddRefHostObject(IntPtr pObject) + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + return V8ProxyHelpers.AddRefHostObject(obj); + } + + [AOT.MonoPInvokeCallback(typeof(RawReleaseHostObject))] + private static void ReleaseHostObject(IntPtr pObject) + { + GCHandle handle = GCHandle.FromIntPtr(pObject); + handle.Free(); + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectInvocability))] + private static Invocability GetHostObjectInvocability(IntPtr pObject) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is InvokeHostObject) + { + return Invocability.Delegate; + } + else +#endif + { + return V8ProxyHelpers.GetHostObjectInvocability(obj); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + return default; + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectNamedProperty))] + private static void GetHostObjectNamedProperty(IntPtr pObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + var value = new V8Value(pValue); + hostObject.GetNamedProperty(name, value, out _); + } + else +#endif + { + string name = StdString.GetValue(pName); + V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(obj, name)); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectNamedPropertyWithCacheability))] + private static void GetHostObjectNamedPropertyWithCacheability(IntPtr pObject, StdString.Ptr pName, V8Value.Ptr pValue, out bool isCacheable) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + var value = new V8Value(pValue); + hostObject.GetNamedProperty(name, value, out isCacheable); + } + else +#endif + { + string name = StdString.GetValue(pName); + V8Value.Set(pValue, V8ProxyHelpers.GetHostObjectProperty(obj, name, out isCacheable)); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + isCacheable = false; + } + } + + [AOT.MonoPInvokeCallback(typeof(RawSetHostObjectNamedProperty))] + private static void SetHostObjectNamedProperty(IntPtr pObject, StdString.Ptr pName, V8Value.Decoded.Ptr pValue) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + var name = new StdString(pName); + + using (var value = *(V8Value.Decoded*)(IntPtr)pValue) + { + hostObject.SetNamedProperty(name, value); + } + } + } + else +#endif + { + string name = StdString.GetValue(pName); + object value = V8Value.Decoded.Get(pValue, 0); + V8ProxyHelpers.SetHostObjectProperty(obj, name, value); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawDeleteHostObjectNamedProperty))] + private static bool DeleteHostObjectNamedProperty(IntPtr pObject, StdString.Ptr pName) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var name = new StdString(pName); + return hostObject.DeleteNamedProperty(name); + } + else +#endif + { + string name = StdString.GetValue(pName); + return V8ProxyHelpers.DeleteHostObjectProperty(obj, name); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + return default; + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectPropertyNames))] + private static void GetHostObjectPropertyNames(IntPtr pObject, StdStringArray.Ptr pNames) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var names = new StdStringArray(pNames); + hostObject.GetNamedPropertyNames(names); + } + else +#endif + { + string[] names = V8ProxyHelpers.GetHostObjectPropertyNames(obj); + StdStringArray.CopyFromArray(pNames, names); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectIndexedProperty))] + private static void GetHostObjectIndexedProperty(IntPtr pObject, int index, V8Value.Ptr pValue) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var value = new V8Value(pValue); + hostObject.GetIndexedProperty(index, value); + } + else +#endif + { + object value = V8ProxyHelpers.GetHostObjectProperty(obj, index); + V8Value.Set(pValue, value); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawSetHostObjectIndexedProperty))] + private static void SetHostObjectIndexedProperty(IntPtr pObject, int index, V8Value.Decoded.Ptr pValue) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + using (var value = *(V8Value.Decoded*)(IntPtr)pValue) + { + hostObject.SetIndexedProperty(index, value); + } + } + } + else +#endif + { + object value = V8Value.Decoded.Get(pValue, 0); + V8ProxyHelpers.SetHostObjectProperty(obj, index, value); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawDeleteHostObjectIndexedProperty))] + private static bool DeleteHostObjectIndexedProperty(IntPtr pObject, int index) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + return hostObject.DeleteIndexedProperty(index); + } + else +#endif + { + return V8ProxyHelpers.DeleteHostObjectProperty(obj, index); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + return default; + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectPropertyIndices))] + private static void GetHostObjectPropertyIndices(IntPtr pObject, StdInt32Array.Ptr pIndices) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var indices = new StdInt32Array(pIndices); + hostObject.GetIndexedPropertyIndices(indices); + } + else +#endif + { + int[] indices = V8ProxyHelpers.GetHostObjectPropertyIndices(obj); + StdInt32Array.CopyFromArray(pIndices, indices); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawInvokeHostObject))] + private static void InvokeHostObject(IntPtr pObject, bool asConstructor, int argCount, V8Value.Decoded.Ptr pArgs, V8Value.Ptr pResult) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is InvokeHostObject method) + { + unsafe + { + var args = new ReadOnlySpan((V8Value.Decoded*)(IntPtr)pArgs, argCount); + var result = new V8Value(pResult); + + try + { + method(args, result); + } + finally + { + for (int i = 0; i < argCount; i++) + { + args[i].Dispose(); + } + } + } + } + else +#endif + { + object[] args = V8Value.Decoded.ToArray(argCount, pArgs); + object result = V8ProxyHelpers.InvokeHostObject(obj, asConstructor, args); + V8Value.Set(pResult, result); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawInvokeHostObjectMethod))] + private static void InvokeHostObjectMethod(IntPtr pObject, StdString.Ptr pName, int argCount, V8Value.Decoded.Ptr pArgs, V8Value.Ptr pResult) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + unsafe + { + var name = new StdString(pName); + var args = new ReadOnlySpan((V8Value.Decoded*)(IntPtr)pArgs, argCount); + var result = new V8Value(pResult); + + try + { + hostObject.InvokeMethod(name, args, result); + } + finally + { + for (int i = 0; i < argCount; i++) + { + args[i].Dispose(); + } + } + } + } + else +#endif + { + string name = StdString.GetValue(pName); + object[] args = V8Value.Decoded.ToArray(argCount, pArgs); + object result = V8ProxyHelpers.InvokeHostObjectMethod(obj, name, args); + V8Value.Set(pResult, result); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectEnumerator))] + private static void GetHostObjectEnumerator(IntPtr pObject, V8Value.Ptr pResult) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var result = new V8Value(pResult); + hostObject.GetEnumerator(result); + } + else +#endif + { + object result = V8ProxyHelpers.GetHostObjectEnumerator(obj); + V8Value.Set(pResult, result); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetHostObjectAsyncEnumerator))] + private static void GetHostObjectAsyncEnumerator(IntPtr pObject, V8Value.Ptr pResult) + { + try + { + object obj = V8ProxyHelpers.GetHostObject(pObject); + +#if NETCOREAPP || NETSTANDARD + if (obj is IV8HostObject hostObject) + { + var result = new V8Value(pResult); + hostObject.GetAsyncEnumerator(result); + } + else +#endif + { + object result = V8ProxyHelpers.GetHostObjectAsyncEnumerator(obj); + V8Value.Set(pResult, result); + } + } + catch (Exception exception) + { + ScheduleHostException(pObject, exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawQueueNativeCallback))] + private static void QueueNativeCallback(NativeCallback.Handle hCallback) + { + MiscHelpers.QueueNativeCallback(new NativeCallbackImpl(hCallback)); + } + + [AOT.MonoPInvokeCallback(typeof(RawCreateNativeCallbackTimer))] + private static IntPtr CreateNativeCallbackTimer(int dueTime, int period, NativeCallback.Handle hCallback) + { + return V8ProxyHelpers.AddRefHostObject(new NativeCallbackTimer(dueTime, period, new NativeCallbackImpl(hCallback))); + } + + [AOT.MonoPInvokeCallback(typeof(RawChangeNativeCallbackTimer))] + private static bool ChangeNativeCallbackTimer(IntPtr pTimer, int dueTime, int period) + { + return V8ProxyHelpers.GetHostObject(pTimer).Change(dueTime, period); + } + + [AOT.MonoPInvokeCallback(typeof(RawDestroyNativeCallbackTimer))] + private static void DestroyNativeCallbackTimer(IntPtr pTimer) + { + V8ProxyHelpers.GetHostObject(pTimer).Dispose(); + V8ProxyHelpers.ReleaseHostObject(pTimer); + } + + [AOT.MonoPInvokeCallback(typeof(RawLoadModule))] + private static void LoadModule(IntPtr pSourceDocumentInfo, StdString.Ptr pSpecifier, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, out ulong uniqueId, out DocumentKind documentKind, StdString.Ptr pCode, out IntPtr pDocumentInfo, V8Value.Ptr pExports) + { + string code; + UniqueDocumentInfo documentInfo; + object exports; + + try + { + code = V8ProxyHelpers.LoadModule(pSourceDocumentInfo, StdString.GetValue(pSpecifier), out documentInfo, out exports); + } + catch (Exception exception) + { + ScheduleHostException(exception); + uniqueId = default; + documentKind = default; + pDocumentInfo = default; + return; + } + + StdString.SetValue(pResourceName, MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName)); + StdString.SetValue(pSourceMapUrl, MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty)); + uniqueId = documentInfo.UniqueId; + documentKind = documentInfo.Category.Kind; + StdString.SetValue(pCode, code); + pDocumentInfo = V8ProxyHelpers.AddRefHostObject(documentInfo); + V8Value.Set(pExports, exports); + } + + [AOT.MonoPInvokeCallback(typeof(RawCreateModuleContext))] + private static void CreateModuleContext(IntPtr pDocumentInfo, StdStringArray.Ptr pNames, StdV8ValueArray.Ptr pValues) + { + IDictionary context; + try + { + context = V8ProxyHelpers.CreateModuleContext(pDocumentInfo); + } + catch (Exception exception) + { + ScheduleHostException(exception); + return; + } + + if (context == null) + { + StdStringArray.SetElementCount(pNames, 0); + StdV8ValueArray.SetElementCount(pValues, 0); + } + else + { + StdStringArray.CopyFromArray(pNames, context.Keys.ToArray()); + StdV8ValueArray.CopyFromArray(pValues, context.Values.ToArray()); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawWriteBytesToStream))] + private static void WriteBytesToStream(IntPtr pStream, IntPtr pBytes, int count) + { + try + { + Stream stream = V8ProxyHelpers.GetHostObject(pStream); + +#if NETCOREAPP || NETSTANDARD + unsafe + { + var bytes = new ReadOnlySpan((byte*)pBytes, count); + stream.Write(bytes); + } +#else + var bytes = new byte[count]; + Marshal.Copy(pBytes, bytes, 0, count); + stream.Write(bytes, 0, count); +#endif + } + catch (Exception exception) + { + ScheduleHostException(exception); + } + } + + [AOT.MonoPInvokeCallback(typeof(RawGetGlobalFlags))] + private static V8GlobalFlags GetGlobalFlags() + { + return V8Settings.GlobalFlags; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs.meta new file mode 100644 index 000000000..789f3eb4d --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyManaged.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 778bb187973c24a4498f2b49035efd79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs new file mode 100644 index 000000000..f9358e6da --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs @@ -0,0 +1,17430 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + + + + + + + + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal static partial class V8SplitProxyNative + { + private static IV8SplitProxyNative CreateInstance() + { + var architecture = RuntimeInformation.ProcessArchitecture; + + + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + + + if (architecture == Architecture.X86) + { + return new Impl_Windows_X86(); + } + + + + if (architecture == Architecture.X64) + { + return new Impl_Windows_X64(); + } + + + + if (architecture == Architecture.Arm64) + { + return new Impl_Windows_Arm64(); + } + + + + throw new PlatformNotSupportedException("Unsupported process architecture"); + } + + + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + + + if (architecture == Architecture.X64) + { + return new Impl_Linux_X64(); + } + + + + if (architecture == Architecture.Arm64) + { + return new Impl_Linux_Arm64(); + } + + + + if (architecture == Architecture.Arm) + { + return new Impl_Linux_Arm(); + } + + + + throw new PlatformNotSupportedException("Unsupported process architecture"); + } + + + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + + + if (architecture == Architecture.X64) + { + return new Impl_OSX_X64(); + } + + + + if (architecture == Architecture.Arm64) + { + return new Impl_OSX_Arm64(); + } + + + + throw new PlatformNotSupportedException("Unsupported process architecture"); + } + + + + throw new PlatformNotSupportedException("Unsupported operating system"); + } + + + + #region Nested type: Impl_Windows_X86 + + private sealed class Impl_Windows_X86 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Windows_X86(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_Windows_X64 + + private sealed class Impl_Windows_X64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Windows_X64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_Windows_Arm64 + + private sealed class Impl_Windows_Arm64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Windows_Arm64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_Linux_X64 + + private sealed class Impl_Linux_X64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Linux_X64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_Linux_Arm64 + + private sealed class Impl_Linux_Arm64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Linux_Arm64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_Linux_Arm + + private sealed class Impl_Linux_Arm : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_Linux_Arm(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_OSX_X64 + + private sealed class Impl_OSX_X64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_OSX_X64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + #region Nested type: Impl_OSX_Arm64 + + private sealed class Impl_OSX_Arm64 : IV8SplitProxyNative + { + public static readonly IV8SplitProxyNative Instance = new Impl_OSX_Arm64(); + + #region IV8SplitProxyNative implementation + + #region initialization + + IntPtr IV8SplitProxyNative.V8SplitProxyManaged_SetMethodTable(IntPtr pMethodTable) + { + return V8SplitProxyManaged_SetMethodTable(pMethodTable); + } + + string IV8SplitProxyNative.V8SplitProxyNative_GetVersion() + { + return Marshal.PtrToStringUni(V8SplitProxyNative_GetVersion()); + } + + void IV8SplitProxyNative.V8Environment_InitializeICU(IntPtr pICUData, uint size) + { + V8Environment_InitializeICU(pICUData, size); + } + + #endregion + + #region StdString methods + + StdString.Ptr IV8SplitProxyNative.StdString_New(string value) + { + return StdString_New(value, value.Length); + } + + string IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString) + { + var pValue = StdString_GetValue(pString, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdString_GetValue(StdString.Ptr pString, out IntPtr value, out int length) + { + value = StdString_GetValue(pString, out length); + } + + void IV8SplitProxyNative.StdString_SetValue(StdString.Ptr pString, string value) + { + StdString_SetValue(pString, value, value.Length); + } + + void IV8SplitProxyNative.StdString_Delete(StdString.Ptr pString) + { + StdString_Delete(pString); + } + + #endregion + + #region StdStringArray methods + + StdStringArray.Ptr IV8SplitProxyNative.StdStringArray_New(int elementCount) + { + return StdStringArray_New(elementCount); + } + + int IV8SplitProxyNative.StdStringArray_GetElementCount(StdStringArray.Ptr pArray) + { + return StdStringArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdStringArray_SetElementCount(StdStringArray.Ptr pArray, int elementCount) + { + StdStringArray_SetElementCount(pArray, elementCount); + } + + string IV8SplitProxyNative.StdStringArray_GetElement(StdStringArray.Ptr pArray, int index) + { + var pValue = StdStringArray_GetElement(pArray, index, out var length); + return Marshal.PtrToStringUni(pValue, length); + } + + void IV8SplitProxyNative.StdStringArray_SetElement(StdStringArray.Ptr pArray, int index, string value) + { + StdStringArray_SetElement(pArray, index, value, value.Length); + } + + void IV8SplitProxyNative.StdStringArray_Delete(StdStringArray.Ptr pArray) + { + StdStringArray_Delete(pArray); + } + + #endregion + + #region StdByteArray methods + + StdByteArray.Ptr IV8SplitProxyNative.StdByteArray_New(int elementCount) + { + return StdByteArray_New(elementCount); + } + + int IV8SplitProxyNative.StdByteArray_GetElementCount(StdByteArray.Ptr pArray) + { + return StdByteArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdByteArray_SetElementCount(StdByteArray.Ptr pArray, int elementCount) + { + StdByteArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdByteArray_GetData(StdByteArray.Ptr pArray) + { + return StdByteArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdByteArray_Delete(StdByteArray.Ptr pArray) + { + StdByteArray_Delete(pArray); + } + + #endregion + + #region StdInt32Array methods + + StdInt32Array.Ptr IV8SplitProxyNative.StdInt32Array_New(int elementCount) + { + return StdInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdInt32Array_GetElementCount(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_SetElementCount(StdInt32Array.Ptr pArray, int elementCount) + { + StdInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdInt32Array_GetData(StdInt32Array.Ptr pArray) + { + return StdInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdInt32Array_Delete(StdInt32Array.Ptr pArray) + { + StdInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt32Array methods + + StdUInt32Array.Ptr IV8SplitProxyNative.StdUInt32Array_New(int elementCount) + { + return StdUInt32Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt32Array_GetElementCount(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_SetElementCount(StdUInt32Array.Ptr pArray, int elementCount) + { + StdUInt32Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt32Array_GetData(StdUInt32Array.Ptr pArray) + { + return StdUInt32Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt32Array_Delete(StdUInt32Array.Ptr pArray) + { + StdUInt32Array_Delete(pArray); + } + + #endregion + + #region StdUInt64Array methods + + StdUInt64Array.Ptr IV8SplitProxyNative.StdUInt64Array_New(int elementCount) + { + return StdUInt64Array_New(elementCount); + } + + int IV8SplitProxyNative.StdUInt64Array_GetElementCount(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_SetElementCount(StdUInt64Array.Ptr pArray, int elementCount) + { + StdUInt64Array_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdUInt64Array_GetData(StdUInt64Array.Ptr pArray) + { + return StdUInt64Array_GetData(pArray); + } + + void IV8SplitProxyNative.StdUInt64Array_Delete(StdUInt64Array.Ptr pArray) + { + StdUInt64Array_Delete(pArray); + } + + #endregion + + #region StdPtrArray methods + + StdPtrArray.Ptr IV8SplitProxyNative.StdPtrArray_New(int elementCount) + { + return StdPtrArray_New(elementCount); + } + + int IV8SplitProxyNative.StdPtrArray_GetElementCount(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_SetElementCount(StdPtrArray.Ptr pArray, int elementCount) + { + StdPtrArray_SetElementCount(pArray, elementCount); + } + + IntPtr IV8SplitProxyNative.StdPtrArray_GetData(StdPtrArray.Ptr pArray) + { + return StdPtrArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdPtrArray_Delete(StdPtrArray.Ptr pArray) + { + StdPtrArray_Delete(pArray); + } + + #endregion + + #region StdV8ValueArray methods + + StdV8ValueArray.Ptr IV8SplitProxyNative.StdV8ValueArray_New(int elementCount) + { + return StdV8ValueArray_New(elementCount); + } + + int IV8SplitProxyNative.StdV8ValueArray_GetElementCount(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetElementCount(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_SetElementCount(StdV8ValueArray.Ptr pArray, int elementCount) + { + StdV8ValueArray_SetElementCount(pArray, elementCount); + } + + V8Value.Ptr IV8SplitProxyNative.StdV8ValueArray_GetData(StdV8ValueArray.Ptr pArray) + { + return StdV8ValueArray_GetData(pArray); + } + + void IV8SplitProxyNative.StdV8ValueArray_Delete(StdV8ValueArray.Ptr pArray) + { + StdV8ValueArray_Delete(pArray); + } + + #endregion + + #region V8Value methods + + V8Value.Ptr IV8SplitProxyNative.V8Value_New() + { + return V8Value_New(); + } + + void IV8SplitProxyNative.V8Value_SetNonexistent(V8Value.Ptr pV8Value) + { + V8Value_SetNonexistent(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetUndefined(V8Value.Ptr pV8Value) + { + V8Value_SetUndefined(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetNull(V8Value.Ptr pV8Value) + { + V8Value_SetNull(pV8Value); + } + + void IV8SplitProxyNative.V8Value_SetBoolean(V8Value.Ptr pV8Value, bool value) + { + V8Value_SetBoolean(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetNumber(V8Value.Ptr pV8Value, double value) + { + V8Value_SetNumber(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetInt32(V8Value.Ptr pV8Value, int value) + { + V8Value_SetInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetUInt32(V8Value.Ptr pV8Value, uint value) + { + V8Value_SetUInt32(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetString(V8Value.Ptr pV8Value, string value) + { + V8Value_SetString(pV8Value, value, value.Length); + } + + void IV8SplitProxyNative.V8Value_SetDateTime(V8Value.Ptr pV8Value, double value) + { + V8Value_SetDateTime(pV8Value, value); + } + + void IV8SplitProxyNative.V8Value_SetBigInt(V8Value.Ptr pV8Value, int signBit, byte[] bytes) + { + V8Value_SetBigInt(pV8Value, signBit, bytes, bytes.Length); + } + + void IV8SplitProxyNative.V8Value_SetV8Object(V8Value.Ptr pV8Value, V8Object.Handle hObject, V8Value.Subtype subtype, V8Value.Flags flags) + { + V8Value_SetV8Object(pV8Value, hObject, subtype, flags); + } + + void IV8SplitProxyNative.V8Value_SetHostObject(V8Value.Ptr pV8Value, IntPtr pObject) + { + V8Value_SetHostObject(pV8Value, pObject); + } + + void IV8SplitProxyNative.V8Value_Decode(V8Value.Ptr pV8Value, out V8Value.Decoded decoded) + { + V8Value_Decode(pV8Value, out decoded); + } + + void IV8SplitProxyNative.V8Value_Delete(V8Value.Ptr pV8Value) + { + V8Value_Delete(pV8Value); + } + + #endregion + + #region V8CpuProfile methods + + void IV8SplitProxyNative.V8CpuProfile_GetInfo(V8CpuProfile.Ptr pProfile, V8Entity.Handle hEntity, out string name, out ulong startTimestamp, out ulong endTimestamp, out int sampleCount, out V8CpuProfile.Node.Ptr pRootNode) + { + using (var nameScope = StdString.CreateScope()) + { + V8CpuProfile_GetInfo(pProfile, hEntity, nameScope.Value, out startTimestamp, out endTimestamp, out sampleCount, out pRootNode); + name = StdString.GetValue(nameScope.Value); + } + } + + bool IV8SplitProxyNative.V8CpuProfile_GetSample(V8CpuProfile.Ptr pProfile, int index, out ulong nodeId, out ulong timestamp) + { + return V8CpuProfile_GetSample(pProfile, index, out nodeId, out timestamp); + } + + void IV8SplitProxyNative.V8CpuProfileNode_GetInfo(V8CpuProfile.Node.Ptr pNode, V8Entity.Handle hEntity, out ulong nodeId, out long scriptId, out string scriptName, out string functionName, out string bailoutReason, out long lineNumber, out long columnNumber, out ulong hitCount, out uint hitLineCount, out int childCount) + { + using (var scriptNameScope = StdString.CreateScope()) + { + using (var functionNameScope = StdString.CreateScope()) + { + using (var bailoutReasonScope = StdString.CreateScope()) + { + V8CpuProfileNode_GetInfo(pNode, hEntity, out nodeId, out scriptId, scriptNameScope.Value, functionNameScope.Value, bailoutReasonScope.Value, out lineNumber, out columnNumber, out hitCount, out hitLineCount, out childCount); + scriptName = StdString.GetValue(scriptNameScope.Value); + functionName = StdString.GetValue(functionNameScope.Value); + bailoutReason = StdString.GetValue(bailoutReasonScope.Value); + + } + } + } + } + + bool IV8SplitProxyNative.V8CpuProfileNode_GetHitLines(V8CpuProfile.Node.Ptr pNode, out int[] lineNumbers, out uint[] hitCounts) + { + using (var lineNumbersScope = StdInt32Array.CreateScope()) + { + using (var hitCountsScope = StdUInt32Array.CreateScope()) + { + var result = V8CpuProfileNode_GetHitLines(pNode, lineNumbersScope.Value, hitCountsScope.Value); + lineNumbers = StdInt32Array.ToArray(lineNumbersScope.Value); + hitCounts = StdUInt32Array.ToArray(hitCountsScope.Value); + return result; + } + } + } + + V8CpuProfile.Node.Ptr IV8SplitProxyNative.V8CpuProfileNode_GetChildNode(V8CpuProfile.Node.Ptr pNode, int index) + { + return V8CpuProfileNode_GetChildNode(pNode, index); + } + + #endregion + + #region V8 isolate methods + + V8Isolate.Handle IV8SplitProxyNative.V8Isolate_Create(string name, int maxNewSpaceSize, int maxOldSpaceSize, double heapExpansionMultiplier, ulong maxArrayBufferAllocation, V8RuntimeFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_Create(nameScope.Value, maxNewSpaceSize, maxOldSpaceSize, heapExpansionMultiplier, maxArrayBufferAllocation, flags, debugPort); + } + } + + V8Context.Handle IV8SplitProxyNative.V8Isolate_CreateContext(V8Isolate.Handle hIsolate, string name, V8ScriptEngineFlags flags, int debugPort) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_CreateContext(hIsolate, nameScope.Value, flags, debugPort); + } + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxHeapSize(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxHeapSize(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxHeapSize(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxHeapSize(hIsolate, size); + } + + double IV8SplitProxyNative.V8Isolate_GetHeapSizeSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetHeapSizeSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetHeapSizeSampleInterval(V8Isolate.Handle hIsolate, double milliseconds) + { + V8Isolate_SetHeapSizeSampleInterval(hIsolate, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Isolate_GetMaxStackUsage(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetMaxStackUsage(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetMaxStackUsage(V8Isolate.Handle hIsolate, UIntPtr size) + { + V8Isolate_SetMaxStackUsage(hIsolate, size); + } + + void IV8SplitProxyNative.V8Isolate_AwaitDebuggerAndPause(V8Isolate.Handle hIsolate) + { + V8Isolate_AwaitDebuggerAndPause(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_CancelAwaitDebugger(V8Isolate.Handle hIsolate) + { + V8Isolate_CancelAwaitDebugger(hIsolate); + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_Compile(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Isolate_Compile(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileProducingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Isolate_CompileProducingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileConsumingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Isolate_CompileConsumingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Isolate_CompileUpdatingCache(V8Isolate.Handle hIsolate, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Isolate_CompileUpdatingCache(hIsolate, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + bool IV8SplitProxyNative.V8Isolate_GetEnableInterruptPropagation(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetEnableInterruptPropagation(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetEnableInterruptPropagation(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetEnableInterruptPropagation(hIsolate, value); + } + + bool IV8SplitProxyNative.V8Isolate_GetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetDisableHeapSizeViolationInterrupt(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetDisableHeapSizeViolationInterrupt(V8Isolate.Handle hIsolate, bool value) + { + V8Isolate_SetDisableHeapSizeViolationInterrupt(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_GetHeapStatistics(V8Isolate.Handle hIsolate, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Isolate_GetHeapStatistics(hIsolate, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Isolate_GetStatistics(V8Isolate.Handle hIsolate, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Isolate_GetStatistics(hIsolate, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Isolate_CollectGarbage(V8Isolate.Handle hIsolate, bool exhaustive) + { + V8Isolate_CollectGarbage(hIsolate, exhaustive); + } + + bool IV8SplitProxyNative.V8Isolate_BeginCpuProfile(V8Isolate.Handle hIsolate, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Isolate_BeginCpuProfile(hIsolate, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Isolate_EndCpuProfile(V8Isolate.Handle hIsolate, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Isolate_EndCpuProfile(hIsolate, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Isolate_CollectCpuProfileSample(V8Isolate.Handle hIsolate) + { + V8Isolate_CollectCpuProfileSample(hIsolate); + } + + uint IV8SplitProxyNative.V8Isolate_GetCpuProfileSampleInterval(V8Isolate.Handle hIsolate) + { + return V8Isolate_GetCpuProfileSampleInterval(hIsolate); + } + + void IV8SplitProxyNative.V8Isolate_SetCpuProfileSampleInterval(V8Isolate.Handle hIsolate, uint value) + { + V8Isolate_SetCpuProfileSampleInterval(hIsolate, value); + } + + void IV8SplitProxyNative.V8Isolate_WriteHeapSnapshot(V8Isolate.Handle hIsolate, IntPtr pStream) + { + V8Isolate_WriteHeapSnapshot(hIsolate, pStream); + } + + #endregion + + #region V8 context methods + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateHeapSize(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateHeapSize(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateHeapSize(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateHeapSize(hContext, size); + } + + double IV8SplitProxyNative.V8Context_GetIsolateHeapSizeSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetIsolateHeapSizeSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetIsolateHeapSizeSampleInterval(V8Context.Handle hContext, double milliseconds) + { + V8Context_SetIsolateHeapSizeSampleInterval(hContext, milliseconds); + } + + UIntPtr IV8SplitProxyNative.V8Context_GetMaxIsolateStackUsage(V8Context.Handle hContext) + { + return V8Context_GetMaxIsolateStackUsage(hContext); + } + + void IV8SplitProxyNative.V8Context_SetMaxIsolateStackUsage(V8Context.Handle hContext, UIntPtr size) + { + V8Context_SetMaxIsolateStackUsage(hContext, size); + } + + void IV8SplitProxyNative.V8Context_InvokeWithLock(V8Context.Handle hContext, IntPtr pAction) + { + V8Context_InvokeWithLock(hContext, pAction); + } + + object IV8SplitProxyNative.V8Context_GetRootItem(V8Context.Handle hContext) + { + using (var itemScope = V8Value.CreateScope()) + { + V8Context_GetRootItem(hContext, itemScope.Value); + return V8Value.Get(itemScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_AddGlobalItem(V8Context.Handle hContext, string name, object value, bool globalMembers) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Context_AddGlobalItem(hContext, nameScope.Value, valueScope.Value, globalMembers); + } + } + } + + void IV8SplitProxyNative.V8Context_AwaitDebuggerAndPause(V8Context.Handle hContext) + { + V8Context_AwaitDebuggerAndPause(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelAwaitDebugger(V8Context.Handle hContext) + { + V8Context_CancelAwaitDebugger(hContext); + } + + object IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteCode(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + } + + void IV8SplitProxyNative.V8Context_ExecuteCode(V8Context.Handle hContext, StdString.Ptr pResourceName, StdString.Ptr pSourceMapUrl, ulong uniquId, DocumentKind documentKind, IntPtr pDocumentInfo, StdString.Ptr pCode, bool evaluate, V8Value.Ptr pResult) + { + V8Context_ExecuteCode(hContext, pResourceName, pSourceMapUrl, uniquId, documentKind, pDocumentInfo, pCode, evaluate, pResult); + } + + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + return V8Context_Compile(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value); + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope()) + { + var hScript = V8Context_CompileProducingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value); + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + return hScript; + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + return V8Context_CompileConsumingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheAccepted); + } + } + } + } + } + + V8Script.Handle IV8SplitProxyNative.V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + using (var codeScope = StdString.CreateScope(code)) + { + using (var cacheBytesScope = StdByteArray.CreateScope(cacheBytes)) + { + var hScript = V8Context_CompileUpdatingCache(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, codeScope.Value, cacheKind, cacheBytesScope.Value, out cacheResult); + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = StdByteArray.ToArray(cacheBytesScope.Value); + } + + return hScript; + } + } + } + } + } + + object IV8SplitProxyNative.V8Context_ExecuteScript(V8Context.Handle hContext, V8Script.Handle hScript, bool evaluate) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Context_ExecuteScript(hContext, hScript, evaluate, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + + void IV8SplitProxyNative.V8Context_Interrupt(V8Context.Handle hContext) + { + V8Context_Interrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_CancelInterrupt(V8Context.Handle hContext) + { + V8Context_CancelInterrupt(hContext); + } + + bool IV8SplitProxyNative.V8Context_GetEnableIsolateInterruptPropagation(V8Context.Handle hContext) + { + return V8Context_GetEnableIsolateInterruptPropagation(hContext); + } + + void IV8SplitProxyNative.V8Context_SetEnableIsolateInterruptPropagation(V8Context.Handle hContext, bool value) + { + V8Context_SetEnableIsolateInterruptPropagation(hContext, value); + } + + bool IV8SplitProxyNative.V8Context_GetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext) + { + return V8Context_GetDisableIsolateHeapSizeViolationInterrupt(hContext); + } + + void IV8SplitProxyNative.V8Context_SetDisableIsolateHeapSizeViolationInterrupt(V8Context.Handle hContext, bool value) + { + V8Context_SetDisableIsolateHeapSizeViolationInterrupt(hContext, value); + } + + void IV8SplitProxyNative.V8Context_GetIsolateHeapStatistics(V8Context.Handle hContext, out ulong totalHeapSize, out ulong totalHeapSizeExecutable, out ulong totalPhysicalSize, out ulong totalAvailableSize, out ulong usedHeapSize, out ulong heapSizeLimit, out ulong totalExternalSize) + { + V8Context_GetIsolateHeapStatistics(hContext, out totalHeapSize, out totalHeapSizeExecutable, out totalPhysicalSize, out totalAvailableSize, out usedHeapSize, out heapSizeLimit, out totalExternalSize); + } + + void IV8SplitProxyNative.V8Context_GetIsolateStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong scriptCacheSize, out ulong moduleCount, out ulong[] postedTaskCounts, out ulong[] invokedTaskCounts) + { + using (var postedTaskCountsScope = StdUInt64Array.CreateScope()) + { + using (var invokedTaskCountsScope = StdUInt64Array.CreateScope()) + { + V8Context_GetIsolateStatistics(hContext, out scriptCount, out scriptCacheSize, out moduleCount, postedTaskCountsScope.Value, invokedTaskCountsScope.Value); + postedTaskCounts = StdUInt64Array.ToArray(postedTaskCountsScope.Value); + invokedTaskCounts = StdUInt64Array.ToArray(invokedTaskCountsScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Context_GetStatistics(V8Context.Handle hContext, out ulong scriptCount, out ulong moduleCount, out ulong moduleCacheSize) + { + V8Context_GetStatistics(hContext, out scriptCount, out moduleCount, out moduleCacheSize); + } + + void IV8SplitProxyNative.V8Context_CollectGarbage(V8Context.Handle hContext, bool exhaustive) + { + V8Context_CollectGarbage(hContext, exhaustive); + } + + void IV8SplitProxyNative.V8Context_OnAccessSettingsChanged(V8Context.Handle hContext) + { + V8Context_OnAccessSettingsChanged(hContext); + } + + bool IV8SplitProxyNative.V8Context_BeginCpuProfile(V8Context.Handle hContext, string name, bool recordSamples) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Context_BeginCpuProfile(hContext, nameScope.Value, recordSamples); + } + } + + void IV8SplitProxyNative.V8Context_EndCpuProfile(V8Context.Handle hContext, string name, IntPtr pAction) + { + using (var nameScope = StdString.CreateScope(name)) + { + V8Context_EndCpuProfile(hContext, nameScope.Value, pAction); + } + } + + void IV8SplitProxyNative.V8Context_CollectCpuProfileSample(V8Context.Handle hContext) + { + V8Context_CollectCpuProfileSample(hContext); + } + + uint IV8SplitProxyNative.V8Context_GetCpuProfileSampleInterval(V8Context.Handle hContext) + { + return V8Context_GetCpuProfileSampleInterval(hContext); + } + + void IV8SplitProxyNative.V8Context_SetCpuProfileSampleInterval(V8Context.Handle hContext, uint value) + { + V8Context_SetCpuProfileSampleInterval(hContext, value); + } + + void IV8SplitProxyNative.V8Context_WriteIsolateHeapSnapshot(V8Context.Handle hContext, IntPtr pStream) + { + V8Context_WriteIsolateHeapSnapshot(hContext, pStream); + } + + #endregion + + #region V8 object methods + + object IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetNamedProperty(hObject, nameScope.Value, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_GetNamedProperty(V8Object.Handle hObject, StdString.Ptr pName, V8Value.Ptr pValue) + { + V8Object_GetNamedProperty(hObject, pName, pValue); + } + + bool IV8SplitProxyNative.V8Object_TryGetNamedProperty(V8Object.Handle hObject, string name, out object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope()) + { + if (V8Object_TryGetNamedProperty(hObject, nameScope.Value, valueScope.Value)) + { + value = V8Value.Get(valueScope.Value); + return true; + } + + value = null; + return false; + } + } + } + + void IV8SplitProxyNative.V8Object_SetNamedProperty(V8Object.Handle hObject, string name, object value) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetNamedProperty(hObject, nameScope.Value, valueScope.Value); + } + } + } + + bool IV8SplitProxyNative.V8Object_DeleteNamedProperty(V8Object.Handle hObject, string name) + { + using (var nameScope = StdString.CreateScope(name)) + { + return V8Object_DeleteNamedProperty(hObject, nameScope.Value); + } + } + + string[] IV8SplitProxyNative.V8Object_GetPropertyNames(V8Object.Handle hObject, bool includeIndices) + { + using (var namesScope = StdStringArray.CreateScope()) + { + V8Object_GetPropertyNames(hObject, includeIndices, namesScope.Value); + return StdStringArray.ToArray(namesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index) + { + using (var valueScope = V8Value.CreateScope()) + { + V8Object_GetIndexedProperty(hObject, index, valueScope.Value); + return V8Value.Get(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetIndexedProperty(V8Object.Handle hObject, int index, V8Value.Ptr pValue) + { + V8Object_GetIndexedProperty(hObject, index, pValue); + } + + void IV8SplitProxyNative.V8Object_SetIndexedProperty(V8Object.Handle hObject, int index, object value) + { + using (var valueScope = V8Value.CreateScope(value)) + { + V8Object_SetIndexedProperty(hObject, index, valueScope.Value); + } + } + + bool IV8SplitProxyNative.V8Object_DeleteIndexedProperty(V8Object.Handle hObject, int index) + { + return V8Object_DeleteIndexedProperty(hObject, index); + } + + int[] IV8SplitProxyNative.V8Object_GetPropertyIndices(V8Object.Handle hObject) + { + using (var indicesScope = StdInt32Array.CreateScope()) + { + V8Object_GetPropertyIndices(hObject, indicesScope.Value); + return StdInt32Array.ToArray(indicesScope.Value); + } + } + + object IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, object[] args) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_Invoke(hObject, asConstructor, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + + void IV8SplitProxyNative.V8Object_Invoke(V8Object.Handle hObject, bool asConstructor, StdV8ValueArray.Ptr pArgs, V8Value.Ptr pResult) + { + V8Object_Invoke(hObject, asConstructor, pArgs, pResult); + } + + object IV8SplitProxyNative.V8Object_InvokeMethod(V8Object.Handle hObject, string name, object[] args) + { + using (var nameScope = StdString.CreateScope(name)) + { + using (var argsScope = StdV8ValueArray.CreateScope(args)) + { + using (var resultScope = V8Value.CreateScope()) + { + V8Object_InvokeMethod(hObject, nameScope.Value, argsScope.Value, resultScope.Value); + return V8Value.Get(resultScope.Value); + } + } + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, out IV8Object arrayBuffer, out ulong offset, out ulong size, out ulong length) + { + using (var arrayBufferScope = V8Value.CreateScope()) + { + V8Object_GetArrayBufferOrViewInfo(hObject, arrayBufferScope.Value, out offset, out size, out length); + arrayBuffer = (IV8Object)V8Value.Get(arrayBufferScope.Value); + } + } + + void IV8SplitProxyNative.V8Object_GetArrayBufferOrViewInfo(V8Object.Handle hObject, V8Value.Ptr pArrayBuffer, out ulong offset, out ulong size, out ulong length) + { + V8Object_GetArrayBufferOrViewInfo(hObject, pArrayBuffer, out offset, out size, out length); + } + + void IV8SplitProxyNative.V8Object_InvokeWithArrayBufferOrViewData(V8Object.Handle hObject, IntPtr pAction) + { + V8Object_InvokeWithArrayBufferOrViewData(hObject, pAction); + } + + #endregion + + #region V8 debug callback methods + + void IV8SplitProxyNative.V8DebugCallback_ConnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_ConnectClient(hCallback); + } + + void IV8SplitProxyNative.V8DebugCallback_SendCommand(V8DebugCallback.Handle hCallback, string command) + { + using (var commandScope = StdString.CreateScope(command)) + { + V8DebugCallback_SendCommand(hCallback, commandScope.Value); + } + } + + void IV8SplitProxyNative.V8DebugCallback_DisconnectClient(V8DebugCallback.Handle hCallback) + { + V8DebugCallback_DisconnectClient(hCallback); + } + + #endregion + + #region native callback methods + + void IV8SplitProxyNative.NativeCallback_Invoke(NativeCallback.Handle hCallback) + { + NativeCallback_Invoke(hCallback); + } + + #endregion + + #region V8 entity cleanup + + void IV8SplitProxyNative.V8Entity_Release(V8Entity.Handle hEntity) + { + V8Entity_Release(hEntity); + } + + void IV8SplitProxyNative.V8Entity_DestroyHandle(V8Entity.Handle hEntity) + { + V8Entity_DestroyHandle(hEntity); + } + + #endregion + + #region error handling + + void IV8SplitProxyNative.HostException_Schedule(string message, object exception) + { + using (var messageScope = StdString.CreateScope(message)) + { + using (var exceptionScope = V8Value.CreateScope(exception)) + { + HostException_Schedule(messageScope.Value, exceptionScope.Value); + } + } + } + + #endregion + + #region unit test support + + UIntPtr IV8SplitProxyNative.V8UnitTestSupport_GetTextDigest(string value) + { + using (var valueScope = StdString.CreateScope(value)) + { + return V8UnitTestSupport_GetTextDigest(valueScope.Value); + } + } + + void IV8SplitProxyNative.V8UnitTestSupport_GetStatistics(out ulong isolateCount, out ulong contextCount) + { + V8UnitTestSupport_GetStatistics(out isolateCount, out contextCount); + } + + #endregion + + #endregion + + #region native methods + + #region initialization + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyManaged_SetMethodTable( + [In] IntPtr pMethodTable + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr V8SplitProxyNative_GetVersion(); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Environment_InitializeICU( + [In] IntPtr pICUData, + [In] uint size + ); + + #endregion + + #region StdString methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdString.Ptr StdString_New( + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdString_GetValue( + [In] StdString.Ptr pString, + [Out] out int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_SetValue( + [In] StdString.Ptr pString, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdString_Delete( + [In] StdString.Ptr pString + ); + + #endregion + + #region StdStringArray methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdStringArray.Ptr StdStringArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdStringArray_GetElementCount( + [In] StdStringArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElementCount( + [In] StdStringArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdStringArray_GetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [Out] out int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_SetElement( + [In] StdStringArray.Ptr pArray, + [In] int index, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdStringArray_Delete( + [In] StdStringArray.Ptr pArray + ); + + #endregion + + #region StdByteArray methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdByteArray.Ptr StdByteArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdByteArray_GetElementCount( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_SetElementCount( + [In] StdByteArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdByteArray_GetData( + [In] StdByteArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdByteArray_Delete( + [In] StdByteArray.Ptr pArray + ); + + #endregion + + #region StdInt32Array methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdInt32Array.Ptr StdInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdInt32Array_GetElementCount( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_SetElementCount( + [In] StdInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdInt32Array_GetData( + [In] StdInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdInt32Array_Delete( + [In] StdInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt32Array methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt32Array.Ptr StdUInt32Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt32Array_GetElementCount( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_SetElementCount( + [In] StdUInt32Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt32Array_GetData( + [In] StdUInt32Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt32Array_Delete( + [In] StdUInt32Array.Ptr pArray + ); + + #endregion + + #region StdUInt64Array methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdUInt64Array.Ptr StdUInt64Array_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdUInt64Array_GetElementCount( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_SetElementCount( + [In] StdUInt64Array.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdUInt64Array_GetData( + [In] StdUInt64Array.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdUInt64Array_Delete( + [In] StdUInt64Array.Ptr pArray + ); + + #endregion + + #region StdPtrArray methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdPtrArray.Ptr StdPtrArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdPtrArray_GetElementCount( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_SetElementCount( + [In] StdPtrArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern IntPtr StdPtrArray_GetData( + [In] StdPtrArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdPtrArray_Delete( + [In] StdPtrArray.Ptr pArray + ); + + #endregion + + #region StdV8ValueArray methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern StdV8ValueArray.Ptr StdV8ValueArray_New( + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern int StdV8ValueArray_GetElementCount( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_SetElementCount( + [In] StdV8ValueArray.Ptr pArray, + [In] int elementCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr StdV8ValueArray_GetData( + [In] StdV8ValueArray.Ptr pArray + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void StdV8ValueArray_Delete( + [In] StdV8ValueArray.Ptr pArray + ); + + #endregion + + #region V8Value methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Value.Ptr V8Value_New(); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNonexistent( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUndefined( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNull( + [In] V8Value.Ptr pV8Value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBoolean( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetNumber( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetInt32( + [In] V8Value.Ptr pV8Value, + [In] int value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetUInt32( + [In] V8Value.Ptr pV8Value, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetString( + [In] V8Value.Ptr pV8Value, + [In] [MarshalAs(UnmanagedType.LPWStr)] string value, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetDateTime( + [In] V8Value.Ptr pV8Value, + [In] double value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetBigInt( + [In] V8Value.Ptr pV8Value, + [In] int signBit, + [In] [MarshalAs(UnmanagedType.LPArray)] byte[] bytes, + [In] int length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetV8Object( + [In] V8Value.Ptr pV8Value, + [In] V8Object.Handle hObject, + [In] V8Value.Subtype subtype, + [In] V8Value.Flags flags + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_SetHostObject( + [In] V8Value.Ptr pV8Value, + [In] IntPtr pObject + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Decode( + [In] V8Value.Ptr pV8Value, + [Out] out V8Value.Decoded decoded + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Value_Delete( + [In] V8Value.Ptr pV8Value + ); + + #endregion + + #region V8CpuProfile methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfile_GetInfo( + [In] V8CpuProfile.Ptr pProfile, + [In] V8Entity.Handle hEntity, + [In] StdString.Ptr pName, + [Out] out ulong startTimestamp, + [Out] out ulong endTimestamp, + [Out] out int sampleCount, + [Out] out V8CpuProfile.Node.Ptr pRootNode + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfile_GetSample( + [In] V8CpuProfile.Ptr pProfile, + [In] int index, + [Out] out ulong nodeId, + [Out] out ulong timestamp + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8CpuProfileNode_GetInfo( + [In] V8CpuProfile.Node.Ptr pNode, + [In] V8Entity.Handle hEntity, + [Out] out ulong nodeId, + [Out] out long scriptId, + [In] StdString.Ptr pScriptName, + [In] StdString.Ptr pFunctionName, + [In] StdString.Ptr pBailoutReason, + [Out] out long lineNumber, + [Out] out long columnNumber, + [Out] out ulong hitCount, + [Out] out uint hitLineCount, + [Out] out int childCount + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8CpuProfileNode_GetHitLines( + [In] V8CpuProfile.Node.Ptr pNode, + [In] StdInt32Array.Ptr pLineNumbers, + [In] StdUInt32Array.Ptr pHitCounts + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8CpuProfile.Node.Ptr V8CpuProfileNode_GetChildNode( + [In] V8CpuProfile.Node.Ptr pNode, + [In] int index + ); + + #endregion + + #region V8 isolate methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Isolate.Handle V8Isolate_Create( + [In] StdString.Ptr pName, + [In] int maxNewSpaceSize, + [In] int maxOldSpaceSize, + [In] double heapExpansionMultiplier, + [In] ulong maxArrayBufferAllocation, + [In] V8RuntimeFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Context.Handle V8Isolate_CreateContext( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] V8ScriptEngineFlags flags, + [In] int debugPort + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxHeapSize( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxHeapSize( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Isolate_GetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetHeapSizeSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Isolate_GetMaxStackUsage( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetMaxStackUsage( + [In] V8Isolate.Handle hIsolate, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_AwaitDebuggerAndPause( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CancelAwaitDebugger( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_Compile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileProducingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileConsumingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Isolate_CompileUpdatingCache( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetEnableInterruptPropagation( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_GetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetDisableHeapSizeViolationInterrupt( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetHeapStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_GetStatistics( + [In] V8Isolate.Handle hIsolate, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectGarbage( + [In] V8Isolate.Handle hIsolate, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Isolate_BeginCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_EndCpuProfile( + [In] V8Isolate.Handle hIsolate, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_CollectCpuProfileSample( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Isolate_GetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_SetCpuProfileSampleInterval( + [In] V8Isolate.Handle hIsolate, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Isolate_WriteHeapSnapshot( + [In] V8Isolate.Handle hIsolate, + [In] IntPtr pStream + ); + + #endregion + + #region V8 context methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateHeapSize( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateHeapSize( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern double V8Context_GetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetIsolateHeapSizeSampleInterval( + [In] V8Context.Handle hContext, + [In] double milliseconds + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8Context_GetMaxIsolateStackUsage( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetMaxIsolateStackUsage( + [In] V8Context.Handle hContext, + [In] UIntPtr size + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_InvokeWithLock( + [In] V8Context.Handle hContext, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetRootItem( + [In] V8Context.Handle hContext, + [In] V8Value.Ptr pItem + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AddGlobalItem( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue, + [In] [MarshalAs(UnmanagedType.I1)] bool globalMembers + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_AwaitDebuggerAndPause( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelAwaitDebugger( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteCode( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_Compile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileProducingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileConsumingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] [MarshalAs(UnmanagedType.I1)] out bool cacheAccepted + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileUpdatingCache( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] StdString.Ptr pCode, + [In] V8CacheKind cacheKind, + [In] StdByteArray.Ptr pCacheBytes, + [Out] out V8CacheResult cacheResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_ExecuteScript( + [In] V8Context.Handle hContext, + [In] V8Script.Handle hScript, + [In] [MarshalAs(UnmanagedType.I1)] bool evaluate, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_Interrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CancelInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetEnableIsolateInterruptPropagation( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_GetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetDisableIsolateHeapSizeViolationInterrupt( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateHeapStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong totalHeapSize, + [Out] out ulong totalHeapSizeExecutable, + [Out] out ulong totalPhysicalSize, + [Out] out ulong totalAvailableSize, + [Out] out ulong usedHeapSize, + [Out] out ulong heapSizeLimit, + [Out] out ulong totalExternalSize + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetIsolateStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong scriptCacheSize, + [Out] out ulong moduleCount, + [In] StdUInt64Array.Ptr pPostedTaskCounts, + [In] StdUInt64Array.Ptr pInvokedTaskCounts + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_GetStatistics( + [In] V8Context.Handle hContext, + [Out] out ulong scriptCount, + [Out] out ulong moduleCount, + [Out] out ulong moduleCacheSize + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectGarbage( + [In] V8Context.Handle hContext, + [In] [MarshalAs(UnmanagedType.I1)] bool exhaustive + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_OnAccessSettingsChanged( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Context_BeginCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] [MarshalAs(UnmanagedType.I1)] bool recordSamples + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_EndCpuProfile( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pName, + [In] IntPtr pAction + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_CollectCpuProfileSample( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern uint V8Context_GetCpuProfileSampleInterval( + [In] V8Context.Handle hContext + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_SetCpuProfileSampleInterval( + [In] V8Context.Handle hContext, + [In] uint value + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Context_WriteIsolateHeapSnapshot( + [In] V8Context.Handle hContext, + [In] IntPtr pStream + ); + + #endregion + + #region V8 object methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_TryGetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteNamedProperty( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyNames( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool includeIndices, + [In] StdStringArray.Ptr pNames + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_SetIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index, + [In] V8Value.Ptr pValue + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool V8Object_DeleteIndexedProperty( + [In] V8Object.Handle hObject, + [In] int index + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetPropertyIndices( + [In] V8Object.Handle hObject, + [In] StdInt32Array.Ptr pIndices + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_Invoke( + [In] V8Object.Handle hObject, + [In] [MarshalAs(UnmanagedType.I1)] bool asConstructor, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeMethod( + [In] V8Object.Handle hObject, + [In] StdString.Ptr pName, + [In] StdV8ValueArray.Ptr pArgs, + [In] V8Value.Ptr pResult + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_GetArrayBufferOrViewInfo( + [In] V8Object.Handle hObject, + [In] V8Value.Ptr pArrayBuffer, + [Out] out ulong offset, + [Out] out ulong size, + [Out] out ulong length + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Object_InvokeWithArrayBufferOrViewData( + [In] V8Object.Handle hObject, + [In] IntPtr pAction + ); + + #endregion + + #region V8 debug callback methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_ConnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_SendCommand( + [In] V8DebugCallback.Handle hCallback, + [In] StdString.Ptr pCommand + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8DebugCallback_DisconnectClient( + [In] V8DebugCallback.Handle hCallback + ); + + #endregion + + #region native callback methods + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void NativeCallback_Invoke( + [In] NativeCallback.Handle hCallback + ); + + #endregion + + #region V8 entity cleanup + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_Release( + [In] V8Entity.Handle hEntity + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8Entity_DestroyHandle( + [In] V8Entity.Handle hEntity + ); + + #endregion + + #region error handling + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void HostException_Schedule( + [In] StdString.Ptr pMessage, + [In] V8Value.Ptr pException + ); + + #endregion + + #region unit test support + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern UIntPtr V8UnitTestSupport_GetTextDigest( + [In] StdString.Ptr pString + ); + + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern void V8UnitTestSupport_GetStatistics( + [Out] out ulong isolateCount, + [Out] out ulong contextCount + ); + + #endregion + + #endregion + } + + #endregion + + + + } +} + diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs.meta new file mode 100644 index 000000000..5e3124aa0 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.Generated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79dbce6d3a00da144ad666a6c3625f65 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs new file mode 100644 index 000000000..567f29cd7 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal static partial class V8SplitProxyNative + { + internal static readonly IV8SplitProxyNative Instance = CreateInstance(); + + public static string GetVersion() + { + try + { + return Instance.V8SplitProxyNative_GetVersion(); + } + catch (EntryPointNotFoundException) + { + return "[unknown]"; + } + } + + public static InvokeScope Invoke(out IV8SplitProxyNative instance) + { + var previousScheduledException = MiscHelpers.Exchange(ref V8SplitProxyManaged.ScheduledException, null); + var previousMethodTable = Instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); + instance = Instance; + return new InvokeScope(previousScheduledException, previousMethodTable); + } + + public static InvokeNoThrowScope InvokeNoThrow(out IV8SplitProxyNative instance) + { + var previousMethodTable = Instance.V8SplitProxyManaged_SetMethodTable(V8SplitProxyManaged.MethodTable); + instance = Instance; + return new InvokeNoThrowScope(previousMethodTable); + } + + private static void ThrowScheduledException() + { + if (V8SplitProxyManaged.ScheduledException != null) + { + throw V8SplitProxyManaged.ScheduledException; + } + } + + public readonly ref struct InvokeNoThrowScope + { + private readonly IntPtr previousMethodTable; + + public InvokeNoThrowScope(IntPtr previousMethodTable) + { + this.previousMethodTable = previousMethodTable; + } + + public void Dispose() + { + Instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); + } + } + + public readonly ref struct InvokeScope + { + private readonly Exception previousScheduledException; + private readonly IntPtr previousMethodTable; + + public InvokeScope(Exception previousScheduledException, IntPtr previousMethodTable) + { + this.previousScheduledException = previousScheduledException; + this.previousMethodTable = previousMethodTable; + } + + public void Dispose() + { + try + { + ThrowScheduledException(); + } + finally + { + Instance.V8SplitProxyManaged_SetMethodTable(previousMethodTable); + V8SplitProxyManaged.ScheduledException = previousScheduledException; + } + } + } + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs.meta new file mode 100644 index 000000000..257bf3f1b --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8SplitProxyNative.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b91d9dbf0bd4bb14f842580e648b9505 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs b/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs new file mode 100644 index 000000000..13f76e1c5 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8.SplitProxy +{ + internal sealed class V8TestProxyImpl : V8TestProxy + { + public override UIntPtr GetNativeDigest(string value) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + return instance.V8UnitTestSupport_GetTextDigest(value); + } + } + + public override Statistics GetStatistics() + { + var statistics = new Statistics(); + + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8UnitTestSupport_GetStatistics(out statistics.IsolateCount, out statistics.ContextCount); + } + + return statistics; + } + + public override void Dispose() + { + } + } +} diff --git a/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs.meta b/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs.meta new file mode 100644 index 000000000..9fba36d53 --- /dev/null +++ b/Unity/Package/Runtime/V8/SplitProxy/V8TestProxyImpl.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: affec7165fd7ba0448f8023acd5cf2f9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs new file mode 100644 index 000000000..e8b871ae7 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.V8 +{ + internal sealed class V8ArrayBufferOrViewInfo + { + public V8ArrayBufferOrViewInfo(V8ArrayBufferOrViewKind kind, IV8Object arrayBuffer, ulong offset, ulong size, ulong length) + { + Kind = kind; + ArrayBuffer = arrayBuffer; + Offset = offset; + Size = size; + Length = length; + } + + public V8ArrayBufferOrViewKind Kind { get; } + + public IV8Object ArrayBuffer { get; } + + public ulong Offset { get; } + + public ulong Size { get; } + + public ulong Length { get; } + } +} diff --git a/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs.meta b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs.meta new file mode 100644 index 000000000..9e24cfb3e --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 517b749abd822e04dbcfe0eb861b690c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs new file mode 100644 index 000000000..7374ef232 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.V8 +{ + internal enum V8ArrayBufferOrViewKind + { + None, + ArrayBuffer, + DataView, + Uint8Array, + Uint8ClampedArray, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + BigUint64Array, + BigInt64Array, + Float32Array, + Float64Array + } +} diff --git a/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs.meta b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs.meta new file mode 100644 index 000000000..7fe136d88 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ArrayBufferOrViewKind.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38c23fa0c4697384184bf200fe190073 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8CacheKind.cs b/Unity/Package/Runtime/V8/V8CacheKind.cs new file mode 100644 index 000000000..3f45f21b5 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CacheKind.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines caching options for V8 script compilation. + /// + public enum V8CacheKind + { + // IMPORTANT: maintain bitwise equivalence with unmanaged enum V8CacheKind + + /// + /// Specifies that no cache data is to be generated or consumed during V8 script + /// compilation. This option results in the most efficient script compilation when no cache + /// data is available. + /// + None, + + /// + /// Selects parser caching. Parser cache data is smaller and less expensive to generate + /// than code cache data, but it is less effective at accelerating recompilation. + /// + [Obsolete("V8 no longer supports parser caching. This option is now equivalent to Code.")] + Parser, + + /// + /// Selects code caching. Code cache data is larger and more expensive to generate than + /// parser cache data, but it is more effective at accelerating recompilation. + /// + Code + } +} diff --git a/Unity/Package/Runtime/V8/V8CacheKind.cs.meta b/Unity/Package/Runtime/V8/V8CacheKind.cs.meta new file mode 100644 index 000000000..46aeda7a9 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CacheKind.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b76938ea1b9bb854f870580c8a7bf023 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8CacheResult.cs b/Unity/Package/Runtime/V8/V8CacheResult.cs new file mode 100644 index 000000000..7d3b54e5e --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CacheResult.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines cache data processing results for V8 script compilation. + /// + public enum V8CacheResult + { + // IMPORTANT: maintain bitwise equivalence with unmanaged enum V8CacheResult + + /// + /// Indicates that cache data processing was disabled because the caller specified + /// V8CacheKind.None. + /// + Disabled, + + /// + /// Indicates that the provided cache data was accepted and used to accelerate script + /// compilation. + /// + Accepted, + + /// + /// Indicates that script compilation was bypassed because a suitable compiled script was + /// found in the V8 runtime's memory, but the provided cache data was verified to be + /// correct. + /// + Verified, + + /// + /// Indicates that the provided cache data was updated because it was empty, stale, or + /// invalid. + /// + Updated, + + /// + /// Indicates that the provided cache data was empty, stale, or invalid, but new cache data + /// could not be generated, and no additional information was provided by the V8 runtime. + /// + UpdateFailed + } +} diff --git a/Unity/Package/Runtime/V8/V8CacheResult.cs.meta b/Unity/Package/Runtime/V8/V8CacheResult.cs.meta new file mode 100644 index 000000000..17d17dfca --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CacheResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a57dc173e31d9c4fae55f05963d0549 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ContextProxy.cs b/Unity/Package/Runtime/V8/V8ContextProxy.cs new file mode 100644 index 000000000..b61ef7648 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ContextProxy.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using Microsoft.ClearScript.V8.SplitProxy; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract class V8ContextProxy : V8Proxy + { + public static V8ContextProxy Create(V8IsolateProxy isolateProxy, string name, V8ScriptEngineFlags flags, int debugPort) + { + return new V8ContextProxyImpl(isolateProxy, name, flags, debugPort); + } + + public abstract UIntPtr MaxIsolateHeapSize { get; set; } + + public abstract TimeSpan IsolateHeapSizeSampleInterval { get; set; } + + public abstract UIntPtr MaxIsolateStackUsage { get; set; } + + public abstract void InvokeWithLock(Action action); + + public abstract object GetRootItem(); + + public abstract void AddGlobalItem(string name, object item, bool globalMembers); + + public abstract void AwaitDebuggerAndPause(); + + public abstract void CancelAwaitDebugger(); + + public abstract object Execute(UniqueDocumentInfo documentInfo, string code, bool evaluate); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult); + + public abstract object Execute(V8Script script, bool evaluate); + + public abstract void Interrupt(); + + public abstract void CancelInterrupt(); + + public abstract bool EnableIsolateInterruptPropagation { get; set; } + + public abstract bool DisableIsolateHeapSizeViolationInterrupt { get; set; } + + public abstract V8RuntimeHeapInfo GetIsolateHeapInfo(); + + public abstract V8Runtime.Statistics GetIsolateStatistics(); + + public abstract V8ScriptEngine.Statistics GetStatistics(); + + public abstract void CollectGarbage(bool exhaustive); + + public abstract void OnAccessSettingsChanged(); + + public abstract bool BeginCpuProfile(string name, V8CpuProfileFlags flags); + + public abstract V8CpuProfile EndCpuProfile(string name); + + public abstract void CollectCpuProfileSample(); + + public abstract uint CpuProfileSampleInterval { get; set; } + + public abstract void WriteIsolateHeapSnapshot(Stream stream); + } +} diff --git a/Unity/Package/Runtime/V8/V8ContextProxy.cs.meta b/Unity/Package/Runtime/V8/V8ContextProxy.cs.meta new file mode 100644 index 000000000..98354a5d0 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ContextProxy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ce541272e9afe843970a1cad3c6b7ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8CpuProfile.cs b/Unity/Package/Runtime/V8/V8CpuProfile.cs new file mode 100644 index 000000000..94e8aaecd --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CpuProfile.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Represents a V8 CPU profile. + /// + public class V8CpuProfile + { + internal V8CpuProfile() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + /// + /// Gets the profile's name. + /// + public string Name { get; internal set; } + + /// + /// Gets the profile's starting timestamp in microseconds. + /// + /// + /// The timestamp specifies an offset relative to an unspecified moment in the past. All + /// timestamps within the profile are relative to the same moment. + /// + public ulong StartTimestamp { get; internal set; } + + /// + /// Gets the profile's ending timestamp in microseconds. + /// + /// + /// The timestamp specifies an offset relative to an unspecified moment in the past. All + /// timestamps within the profile are relative to the same moment. + /// + public ulong EndTimestamp { get; internal set; } + + /// + /// Gets the root node of the profile's call tree. + /// + public Node RootNode { get; internal set; } + + /// + /// Gets the profile's sample collection. + /// + /// + /// This property returns null if the profile contains no samples. + /// + public IReadOnlyList Samples { get; internal set; } + + /// + /// Returns a JSON representation of the profile. + /// + /// + /// See the + /// V8 Inspector JSON Protocol + /// for schema details. + /// + /// A JSON representation of the profile in V8 Inspector format. + public string ToJson() + { + using (var writer = new StringWriter()) + { + WriteJson(writer); + return writer.ToString(); + } + } + + /// + /// Writes a JSON representation of the profile to the given text writer. + /// + /// The text writer to which to write the profile. + /// + /// See the + /// V8 Inspector JSON Protocol + /// for schema details. + /// + public void WriteJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + writer.Write('{'); + { + WriteNodesJson(writer); + writer.Write(",\"startTime\":" + StartTimestamp); + writer.Write(",\"endTime\":" + EndTimestamp); + WriteSamplesJson(writer); + WriteTimeDeltasJson(writer); + } + writer.Write('}'); + } + + internal Node FindNode(ulong nodeId) + { + return RootNode?.FindNode(nodeId); + } + + private void WriteNodesJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + writer.Write("\"nodes\":["); + { + if (RootNode != null) + { + var queue = new Queue(); + RootNode.WriteJson(writer, queue); + while (queue.Count > 0) + { + writer.Write(','); + queue.Dequeue().WriteJson(writer, queue); + } + } + } + writer.Write(']'); + } + + private void WriteSamplesJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + if ((Samples != null) && (Samples.Count > 0)) + { + writer.Write(",\"samples\":[{0}]", string.Join(",", Samples.Select(sample => sample.Node.NodeId))); + } + } + + private void WriteTimeDeltasJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + if ((Samples != null) && (Samples.Count > 0)) + { + const ulong maxSafeInteger = 9007199254740991UL; // 2^53 - 1 + + writer.Write(",\"timeDeltas\":["); + { + writer.Write(Samples[0].Timestamp - StartTimestamp); + for (var index = 1; index < Samples.Count; index++) + { + var current = Samples[index].Timestamp; + var previous = Samples[index - 1].Timestamp; + + var delta = (current > previous) ? (current - previous) : 0; + delta = Math.Min(delta, maxSafeInteger); + + writer.Write(','); + writer.Write(delta); + } + } + writer.Write(']'); + } + } + + #region Nested type: Node + + /// + /// Represents a node in a V8 CPU profile's call tree. + /// + public sealed class Node + { + internal Node() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + /// + /// Gets the node's numeric identifier. + /// + /// + /// This value is unique within the profile. + /// + public ulong NodeId { get; set; } + + /// + /// Gets the numeric identifier of the document containing the node's script function. + /// + public long ScriptId { get; set; } + + /// + /// Gets the name or URL of the document containing the node's script function. + /// + public string ScriptName { get; internal set; } + + /// + /// Gets the name of the node's script function. + /// + public string FunctionName { get; internal set; } + + /// + /// Gets the 1-based line number of the start of the node's script function. + /// + /// + /// A value of zero indicates that no line number is available. + /// + /// + public long LineNumber { get; internal set; } + + /// + /// Gets the 1-based column number of the start of the node's script function. + /// + /// + /// A value of zero indicates that no column number is available. + /// + /// + public long ColumnNumber { get; internal set; } + + /// + /// Gets the node's hit count. + /// + /// + /// This value represents the number of times the CPU profiler observed the node's + /// script function at the top of the call stack. + /// + public ulong HitCount { get; internal set; } + + /// + /// Gets an optional string describing the reason why the node's script function was not optimized. + /// + public string BailoutReason { get; internal set; } + + /// + /// Gets the node's hit line collection. + /// + /// + /// This property returns null if the node contains no hit lines. + /// + public IReadOnlyList HitLines { get; internal set; } + + /// + /// Gets the node's child node collection. + /// + /// + /// This property returns null if the node has no child nodes. + /// + public IReadOnlyList ChildNodes { get; internal set; } + + internal Node FindNode(ulong nodeId) + { + if (NodeId == nodeId) + { + return this; + } + + if (ChildNodes != null) + { + foreach (var childNode in ChildNodes) + { + var node = childNode.FindNode(nodeId); + if (node != null) + { + return node; + } + } + } + + return null; + } + + internal void WriteJson(TextWriter writer, Queue queue) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + writer.Write('{'); + { + writer.Write("\"id\":" + NodeId); + + WriteCallFrameJson(writer); + writer.Write(",\"hitCount\":" + HitCount); + WriteChildrenJson(writer, queue); + + if (!string.IsNullOrEmpty(BailoutReason)) + { + writer.Write(",\"deoptReason\":" + BailoutReason.ToQuotedJson()); + } + + WritePositionTicksJson(writer); + } + writer.Write('}'); + } + + private void WriteCallFrameJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + writer.Write(",\"callFrame\":{"); + { + writer.Write("\"functionName\":" + (FunctionName ?? string.Empty).ToQuotedJson()); + writer.Write(",\"scriptId\":" + ScriptId); + writer.Write(",\"url\":" + (ScriptName ?? string.Empty).ToQuotedJson()); + writer.Write(",\"lineNumber\":" + (LineNumber - 1)); + writer.Write(",\"columnNumber\":" + (ColumnNumber - 1)); + } + writer.Write('}'); + } + + private void WriteChildrenJson(TextWriter writer, Queue queue) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + if ((ChildNodes != null) && (ChildNodes.Count > 0)) + { + writer.Write(",\"children\":[{0}]", string.Join(",", ChildNodes.Select(node => node.NodeId))); + ChildNodes.ForEach(queue.Enqueue); + } + } + + private void WritePositionTicksJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + if ((HitLines != null) && (HitLines.Count > 0)) + { + writer.Write(",\"positionTicks\":["); + { + HitLines[0].WriteJson(writer); + for (var index = 1; index < HitLines.Count; index++) + { + writer.Write(','); + HitLines[index].WriteJson(writer); + } + } + writer.Write(']'); + } + } + + #region Nested type: HitLine + + /// + /// Represents a script line observed by the V8 CPU profiler. + /// + public struct HitLine + { + /// + /// Gets the 1-based line number. + /// + public long LineNumber; + + /// + /// Gets the hit count for the script line. + /// + /// + /// This value represents the number of times the CPU profiler observed the current + /// script line at the top of the call stack. + /// + public ulong HitCount; + + internal void WriteJson(TextWriter writer) + { + // V8 Inspector JSON Protocol 1.3: https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/inspector/js_protocol-1.3.json + + writer.Write("{{\"line\":{0},\"ticks\":{1}}}", LineNumber, HitCount); + } + } + + #endregion + } + + #endregion + + #region Nested type: Sample + + /// + /// Represents a V8 CPU profile sample. + /// + public sealed class Sample + { + internal Sample() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + /// + /// Gets the sample's node within the profile's call tree. + /// + public Node Node { get; internal set; } + + /// + /// Gets the sample's timestamp in microseconds. + /// + /// + /// The timestamp specifies an offset relative to an unspecified moment in the past. All + /// timestamps within the profile are relative to the same moment. + /// + public ulong Timestamp { get; internal set; } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8CpuProfile.cs.meta b/Unity/Package/Runtime/V8/V8CpuProfile.cs.meta new file mode 100644 index 000000000..ef262573f --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CpuProfile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b702411a58f0dd49baab53d4dddd824 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs b/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs new file mode 100644 index 000000000..8a6564a21 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs @@ -0,0 +1,21 @@ +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines options for creating a V8 CPU profile. + /// + [Flags] + public enum V8CpuProfileFlags + { + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that automatic sample collection is to be enabled. + /// + EnableSampleCollection = 0x00000001 + } +} diff --git a/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs.meta b/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs.meta new file mode 100644 index 000000000..6b5887b9b --- /dev/null +++ b/Unity/Package/Runtime/V8/V8CpuProfileFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29aba5cd54a558a4d88f64fae0e8a0af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8DebugAgent.cs b/Unity/Package/Runtime/V8/V8DebugAgent.cs new file mode 100644 index 000000000..883b04ddb --- /dev/null +++ b/Unity/Package/Runtime/V8/V8DebugAgent.cs @@ -0,0 +1,330 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ClearScript.Properties; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.Web; + +namespace Microsoft.ClearScript.V8 +{ + internal sealed class V8DebugAgent : IDisposable + { + #region data + + private const string faviconUrl = "https://microsoft.github.io/ClearScript/favicon.png"; + + private readonly Guid targetId = Guid.NewGuid(); + private readonly string name; + private readonly string version; + private readonly int port; + private readonly IV8DebugListener listener; + + private TcpListener tcpListener; + private V8DebugClient activeClient; + + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + #endregion + + #region constructors + + public V8DebugAgent(string name, string version, int port, bool remote, IV8DebugListener listener) + { + this.name = name; + this.version = version; + this.port = port; + this.listener = listener; + + var started = false; + + if (remote) + { + started = MiscHelpers.Try(() => + { + tcpListener = new TcpListener(IPAddress.Any, port); + tcpListener.Start(); + }); + } + + if (!started) + { + started = MiscHelpers.Try(() => + { + tcpListener = new TcpListener(IPAddress.Loopback, port); + tcpListener.Start(); + }); + } + + if (started) + { + StartAcceptWebClient(); + } + } + + #endregion + + #region public members + + public void SendCommand(V8DebugClient client, string command) + { + if (client == activeClient) + { + listener.SendCommand(command); + } + } + + public void SendMessage(string message) + { + if (!disposedFlag.IsSet) + { + var client = activeClient; + client?.SendMessage(message); + } + } + + public void OnClientFailed(V8DebugClient client) + { + if (Interlocked.CompareExchange(ref activeClient, null, client) == client) + { + listener.DisconnectClient(); + ThreadPool.QueueUserWorkItem(_ => V8Runtime.OnDebuggerDisconnected(new V8RuntimeDebuggerEventArgs(name, port))); + } + } + + #endregion + + #region Web endpoint + + private void StartAcceptWebClient() + { + tcpListener.AcceptSocketAsync().ContinueWith(OnWebClientAccepted); + } + + private void OnWebClientAccepted(Task task) + { + var succeeded = MiscHelpers.Try(out var socket, () => task.Result); + + if (!disposedFlag.IsSet) + { + if (succeeded) + { + WebContext.CreateAsync(socket).ContinueWith(OnWebContextCreated); + } + + StartAcceptWebClient(); + } + } + + private void OnWebContextCreated(Task task) + { + if (MiscHelpers.Try(out var webContext, () => task.Result) && !disposedFlag.IsSet) + { + if (!webContext.Request.IsWebSocketRequest) + { + HandleWebRequest(webContext); + } + else if (!webContext.Request.RawUrl.Equals("/" + targetId, StringComparison.OrdinalIgnoreCase)) + { + webContext.Response.Close(404); + } + else + { + StartAcceptWebSocket(webContext); + } + } + } + + private void HandleWebRequest(WebContext webContext) + { + // https://github.com/buggerjs/bugger-daemon/blob/master/README.md#api, + // https://github.com/nodejs/node/blob/master/src/inspector_socket_server.cc + + if (webContext.Request.RawUrl.Equals("/json", StringComparison.OrdinalIgnoreCase) || + webContext.Request.RawUrl.Equals("/json/list", StringComparison.OrdinalIgnoreCase)) + { + if (activeClient != null) + { + SendWebResponse(webContext, MiscHelpers.FormatInvariant( + "[ {{\r\n" + + " \"id\": \"{0}\",\r\n" + + " \"type\": \"node\",\r\n" + + " \"description\": \"ClearScript V8 runtime: {1}\",\r\n" + + " \"title\": \"{2}\",\r\n" + + " \"url\": \"{3}\",\r\n" + + " \"faviconUrl\": \"{4}\"\r\n" + + "}} ]\r\n", + targetId, + JsonEscape(name), + JsonEscape(AppDomain.CurrentDomain.FriendlyName), + JsonEscape(new Uri(Process.GetCurrentProcess().MainModule.FileName)), + faviconUrl + )); + } + else + { + SendWebResponse(webContext, MiscHelpers.FormatInvariant( + "[ {{\r\n" + + " \"id\": \"{0}\",\r\n" + + " \"type\": \"node\",\r\n" + + " \"description\": \"ClearScript V8 runtime: {1}\",\r\n" + + " \"title\": \"{2}\",\r\n" + + " \"url\": \"{3}\",\r\n" + + " \"faviconUrl\": \"{6}\",\r\n" + + " \"devtoolsFrontendUrl\": \"devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws={4}:{5}/{0}\",\r\n" + + " \"devtoolsFrontendUrlCompat\": \"devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws={4}:{5}/{0}\",\r\n" + + " \"webSocketDebuggerUrl\": \"ws://{4}:{5}/{0}\"\r\n" + + "}} ]\r\n", + targetId, + JsonEscape(name), + JsonEscape(AppDomain.CurrentDomain.FriendlyName), + JsonEscape(new Uri(Process.GetCurrentProcess().MainModule.FileName)), + webContext.Request.Uri.Host, + webContext.Request.Uri.Port, + faviconUrl + )); + } + } + else if (webContext.Request.RawUrl.Equals("/json/version", StringComparison.OrdinalIgnoreCase)) + { + SendWebResponse(webContext, MiscHelpers.FormatInvariant( + "{{\r\n" + + " \"Browser\": \"ClearScript/v{0}, V8 {1}\",\r\n" + + " \"Protocol-Version\": \"1.1\"\r\n" + + "}}\r\n", + ClearScriptVersion.Informational, + version + )); + } + else if (webContext.Request.RawUrl.StartsWith("/json/activate/", StringComparison.OrdinalIgnoreCase)) + { + var requestTargetId = webContext.Request.RawUrl.Substring(15); + if (requestTargetId.Equals(targetId.ToString(), StringComparison.OrdinalIgnoreCase)) + { + SendWebResponse(webContext, "Target activated", "text/plain"); + } + else + { + SendWebResponse(webContext, "No such target id: " + requestTargetId, "text/plain", 404); + } + } + else if (webContext.Request.RawUrl.StartsWith("/json/close/", StringComparison.OrdinalIgnoreCase)) + { + var requestTargetId = webContext.Request.RawUrl.Substring(12); + if (requestTargetId.Equals(targetId.ToString(), StringComparison.OrdinalIgnoreCase)) + { + SendWebResponse(webContext, "Target is closing", "text/plain"); + } + else + { + SendWebResponse(webContext, "No such target id: " + requestTargetId, "text/plain", 404); + } + } + else if (webContext.Request.RawUrl.StartsWith("/json/new?", StringComparison.OrdinalIgnoreCase) || + webContext.Request.RawUrl.Equals("/json/protocol", StringComparison.OrdinalIgnoreCase)) + { + webContext.Response.Close(501); + } + else + { + webContext.Response.Close(404); + } + } + + #endregion + + #region WebSocket client connection + + private void StartAcceptWebSocket(WebContext webContext) + { + webContext.AcceptWebSocketAsync().ContinueWith(task => OnWebSocketAccepted(webContext, task)); + } + + private void OnWebSocketAccepted(WebContext webContext, Task task) + { + if (MiscHelpers.Try(out var webSocket, () => task.Result)) + { + if (!ConnectClient(webSocket)) + { + webSocket.Close(WebSocket.ErrorCode.PolicyViolation, "A debugger is already connected"); + } + } + else + { + webContext.Response.Close(500); + } + } + + private bool ConnectClient(WebSocket webSocket) + { + var client = new V8DebugClient(this, webSocket); + if (Interlocked.CompareExchange(ref activeClient, client, null) == null) + { + listener.ConnectClient(); + client.Start(); + ThreadPool.QueueUserWorkItem(_ => V8Runtime.OnDebuggerConnected(new V8RuntimeDebuggerEventArgs(name, port))); + return true; + } + + return false; + } + + private void DisconnectClient(WebSocket.ErrorCode errorCode, string message) + { + var client = Interlocked.Exchange(ref activeClient, null); + if (client != null) + { + client.Dispose(errorCode, message); + listener.DisconnectClient(); + ThreadPool.QueueUserWorkItem(_ => V8Runtime.OnDebuggerDisconnected(new V8RuntimeDebuggerEventArgs(name, port))); + } + } + + #endregion + + #region IDisposable implementation + + public void Dispose() + { + if (disposedFlag.Set()) + { + if (tcpListener != null) + { + MiscHelpers.Try(tcpListener.Stop); + } + + DisconnectClient(WebSocket.ErrorCode.EndpointUnavailable, "The V8 runtime has been destroyed"); + listener.Dispose(); + } + } + + #endregion + + #region protocol utilities + + private static void SendWebResponse(WebContext webContext, string content, string contentType = "application/json", int statusCode = 200) + { + using (webContext.Response) + { + var contentBytes = Encoding.UTF8.GetBytes(content); + webContext.Response.ContentType = contentType + "; charset=UTF-8"; + webContext.Response.OutputStream.Write(contentBytes, 0, contentBytes.Length); + webContext.Response.StatusCode = statusCode; + } + } + + private static string JsonEscape(object value) + { + return new string(value.ToString().Select(ch => ((ch == '\"') || (ch == '\\')) ? '_' : ch).ToArray()); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8DebugAgent.cs.meta b/Unity/Package/Runtime/V8/V8DebugAgent.cs.meta new file mode 100644 index 000000000..c5faa97e7 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8DebugAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff52d7acc4142ea4cbe9152110ad8c42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8DebugClient.cs b/Unity/Package/Runtime/V8/V8DebugClient.cs new file mode 100644 index 000000000..d2f0284e9 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8DebugClient.cs @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.Web; + +namespace Microsoft.ClearScript.V8 +{ + [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "This class uses a custom method for deterministic teardown.")] + internal sealed class V8DebugClient + { + #region data + + private readonly V8DebugAgent agent; + private readonly WebSocket webSocket; + + private readonly ConcurrentQueue queue = new ConcurrentQueue(); + private readonly SemaphoreSlim sendSemaphore = new SemaphoreSlim(1); + + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + #endregion + + #region initialization + + public V8DebugClient(V8DebugAgent agent, WebSocket webSocket) + { + this.agent = agent; + this.webSocket = webSocket; + } + + public void Start() + { + StartReceiveMessage(); + } + + #endregion + + #region inbound message reception + + private void StartReceiveMessage() + { + webSocket.ReceiveMessageAsync().ContinueWith(OnMessageReceived); + } + + private void OnMessageReceived(Task task) + { + try + { + var message = task.Result; + if (!disposedFlag.IsSet) + { + if (message.IsBinary) + { + OnFailed(WebSocket.ErrorCode.InvalidMessageType, "Received unexpected binary message from WebSocket"); + } + else + { + agent.SendCommand(this, Encoding.UTF8.GetString(message.Payload)); + StartReceiveMessage(); + } + } + } + catch (AggregateException aggregateException) + { + aggregateException.Handle(exception => + { + if (!disposedFlag.IsSet) + { + if (exception is WebSocket.Exception webSocketException) + { + OnFailed(webSocketException.ErrorCode, webSocketException.Message); + } + else + { + OnFailed(WebSocket.ErrorCode.ProtocolError, "Could not receive message from WebSocket"); + } + } + + return true; + }); + } + } + + #endregion + + #region outbound message delivery + + public void SendMessage(string message) + { + if (!disposedFlag.IsSet) + { + queue.Enqueue(message); + SendMessagesAsync().ContinueWith(OnMessagesSent); + } + } + + private async Task SendMessagesAsync() + { + using (await sendSemaphore.CreateLockScopeAsync().ConfigureAwait(false)) + { + while (queue.TryDequeue(out var message)) + { + await webSocket.SendMessageAsync(Encoding.UTF8.GetBytes(message)).ConfigureAwait(false); + } + } + } + + private void OnMessagesSent(Task task) + { + try + { + task.Wait(); + } + catch (AggregateException aggregateException) + { + aggregateException.Handle(exception => + { + if (!disposedFlag.IsSet) + { + if (exception is WebSocket.Exception webSocketException) + { + OnFailed(webSocketException.ErrorCode, webSocketException.Message); + } + else + { + OnFailed(WebSocket.ErrorCode.ProtocolError, "Could not send message to WebSocket"); + } + } + + return true; + }); + } + } + + #endregion + + #region teardown + + private void OnFailed(WebSocket.ErrorCode errorCode, string message) + { + Dispose(errorCode, message); + agent.OnClientFailed(this); + } + + public void Dispose(WebSocket.ErrorCode errorCode, string message) + { + if (disposedFlag.Set()) + { + webSocket.Close(errorCode, message); + sendSemaphore.Dispose(); + } + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8DebugClient.cs.meta b/Unity/Package/Runtime/V8/V8DebugClient.cs.meta new file mode 100644 index 000000000..c5a19751a --- /dev/null +++ b/Unity/Package/Runtime/V8/V8DebugClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0a2496d1c1abf524d95115e1feb682ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8GlobalFlags.cs b/Unity/Package/Runtime/V8/V8GlobalFlags.cs new file mode 100644 index 000000000..be843f9a5 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8GlobalFlags.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines global V8 options. + /// + [Flags] + public enum V8GlobalFlags : uint + { + // IMPORTANT: maintain bitwise equivalence with unmanaged enum V8GlobalFlags + + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that Top-Level Await is to be enabled. + /// + [Obsolete("V8 no longer supports Top-Level Await control. The feature is always enabled.")] + EnableTopLevelAwait = 0x00000001, + + /// + /// Specifies that just-in-time compilation is to be disabled. + /// + DisableJITCompilation = 0x00000002, + + /// + /// Specifies that background work is to be disabled. By default, V8 performs various tasks + /// in the background, accelerating garbage collection, just-in-time compilation, and other + /// activities. Use this option if you encounter issues related to V8's background work. + /// + DisableBackgroundWork = 0x00000004 + } +} diff --git a/Unity/Package/Runtime/V8/V8GlobalFlags.cs.meta b/Unity/Package/Runtime/V8/V8GlobalFlags.cs.meta new file mode 100644 index 000000000..e24d38706 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8GlobalFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9a3964ee6c324140a287bf66d230bac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8IsolateProxy.cs b/Unity/Package/Runtime/V8/V8IsolateProxy.cs new file mode 100644 index 000000000..7acfe4512 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8IsolateProxy.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using Microsoft.ClearScript.V8.SplitProxy; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract class V8IsolateProxy : V8Proxy + { + public static V8IsolateProxy Create(string name, V8RuntimeConstraints constraints, V8RuntimeFlags flags, int debugPort) + { + return new V8IsolateProxyImpl(name, constraints, flags, debugPort); + } + + public abstract UIntPtr MaxHeapSize { get; set; } + + public abstract TimeSpan HeapSizeSampleInterval { get; set; } + + public abstract UIntPtr MaxStackUsage { get; set; } + + public abstract void AwaitDebuggerAndPause(); + + public abstract void CancelAwaitDebugger(); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); + + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult); + + public abstract bool EnableInterruptPropagation { get; set; } + + public abstract bool DisableHeapSizeViolationInterrupt { get; set; } + + public abstract V8RuntimeHeapInfo GetHeapInfo(); + + public abstract V8Runtime.Statistics GetStatistics(); + + public abstract void CollectGarbage(bool exhaustive); + + public abstract bool BeginCpuProfile(string name, V8CpuProfileFlags flags); + + public abstract V8CpuProfile EndCpuProfile(string name); + + public abstract void CollectCpuProfileSample(); + + public abstract uint CpuProfileSampleInterval { get; set; } + + public abstract void WriteHeapSnapshot(Stream stream); + } +} diff --git a/Unity/Package/Runtime/V8/V8IsolateProxy.cs.meta b/Unity/Package/Runtime/V8/V8IsolateProxy.cs.meta new file mode 100644 index 000000000..4f24cf6a6 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8IsolateProxy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4d8240d3943e85a40af64a860fbdfe3f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs b/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs new file mode 100644 index 000000000..6443a25e4 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract partial class V8Proxy + { + private static IntPtr LoadLibrary(string path) + { + return NativeMethods.LoadLibrary(path); + } + + private static void FreeLibrary(IntPtr hLibrary) + { + NativeMethods.FreeLibrary(hLibrary); + } + + private static string GetLoadLibraryErrorMessage() + { + return NativeMethods.GetLoadLibraryErrorMessage(); + } + } +} diff --git a/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs.meta b/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs.meta new file mode 100644 index 000000000..fe53e4f60 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Proxy.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df256b7f6df54e74cb97048c5228dd73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8Proxy.cs b/Unity/Package/Runtime/V8/V8Proxy.cs new file mode 100644 index 000000000..2d107c713 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Proxy.cs @@ -0,0 +1,224 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.ClearScript.Properties; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.V8.ICUData; +using Microsoft.ClearScript.V8.SplitProxy; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract partial class V8Proxy : IDisposable + { + private static readonly object dataLock = new object(); + + private static IntPtr hNativeAssembly; + private static ulong splitImplCount; + private static bool triedToLoadNativeAssembly; + private static bool loadedNativeAssembly; + + internal static void OnEntityHolderCreated() + { + lock (dataLock) + { + if (++splitImplCount == 1) + { + V8SplitProxyManaged.Initialize(); + } + + if (!triedToLoadNativeAssembly) + { + triedToLoadNativeAssembly = true; + + var nativeVersion = string.Empty; + var gotNativeVersion = false; + + try + { + hNativeAssembly = LoadNativeAssembly(); + loadedNativeAssembly = true; + } + catch + { + gotNativeVersion = MiscHelpers.Try(out nativeVersion, V8SplitProxyNative.GetVersion); + if (!gotNativeVersion) + { + throw; + } + } + + if (!gotNativeVersion) + { + nativeVersion = V8SplitProxyNative.GetVersion(); + } + + if (nativeVersion != ClearScriptVersion.Informational) + { + throw new InvalidOperationException($"V8 native assembly: loaded version {nativeVersion} does not match required version {ClearScriptVersion.Informational}"); + } + + InitializeICU(); + } + } + } + + internal static void OnEntityHolderDestroyed() + { + lock (dataLock) + { + if (--splitImplCount < 1) + { + V8SplitProxyManaged.Teardown(); + + if (loadedNativeAssembly) + { + FreeLibrary(hNativeAssembly); + hNativeAssembly = IntPtr.Zero; + loadedNativeAssembly = false; + } + } + } + } + + private static IntPtr LoadNativeAssembly() + { + string platform; + string architecture; + string extension; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + platform = "win"; + extension = "dll"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + platform = "linux"; + extension = "so"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + platform = "osx"; + extension = "dylib"; + } + else + { + throw new PlatformNotSupportedException("Unsupported OS platform"); + } + + if (RuntimeInformation.ProcessArchitecture == Architecture.X64) + { + architecture = "x64"; + } + else if (RuntimeInformation.ProcessArchitecture == Architecture.X86) + { + architecture = "x86"; + } + else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm) + { + architecture = "arm"; + } + else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + { + architecture = "arm64"; + } + else + { + throw new PlatformNotSupportedException("Unsupported process architecture"); + } + + return LoadNativeLibrary("ClearScriptV8", platform, architecture, extension); + } + + private static IntPtr LoadNativeLibrary(string baseName, string platform, string architecture, string extension) + { + var fileName = $"{baseName}.{platform}-{architecture}.{extension}"; + var messageBuilder = new StringBuilder(); + + var paths = GetDirPaths(platform, architecture).Select(dirPath => Path.Combine(dirPath, fileName)).Distinct(); + foreach (var path in paths) + { + var hLibrary = LoadLibrary(path); + if (hLibrary != IntPtr.Zero) + { + return hLibrary; + } + + messageBuilder.AppendInvariant("\n{0}: {1}", path, MiscHelpers.EnsureNonBlank(GetLoadLibraryErrorMessage(), "Unknown error")); + } + + var message = MiscHelpers.FormatInvariant("Cannot load ClearScript V8 library. Load failure information for {0}:{1}", fileName, messageBuilder); + throw new TypeLoadException(message); + } + + private static unsafe void InitializeICU() + { + using (var stream = typeof(V8ICUData).Assembly.GetManifestResourceStream(V8ICUData.ResourceName)) + { + var bytes = new byte[stream.Length]; + + var length = stream.Read(bytes, 0, bytes.Length); + Debug.Assert(length == bytes.Length); + + fixed (byte* pBytes = bytes) + { + using (V8SplitProxyNative.InvokeNoThrow(out var instance)) + { + instance.V8Environment_InitializeICU((IntPtr)pBytes, Convert.ToUInt32(length)); + } + } + } + } + + private static IEnumerable GetDirPaths(string platform, string architecture) + { + // The assembly location may be empty if the host preloaded the assembly + // from custom storage. Support for this scenario was requested on CodePlex. + + var location = typeof(V8Proxy).Assembly.Location; + if (!string.IsNullOrWhiteSpace(location)) + { + if ((platform != null) && (architecture != null)) + { + yield return Path.Combine(Path.GetDirectoryName(location), "runtimes", $"{platform}-{architecture}", "native"); + } + + yield return Path.GetDirectoryName(location); + } + + var appDomain = AppDomain.CurrentDomain; + yield return appDomain.BaseDirectory; + + var searchPath = appDomain.RelativeSearchPath; + if (!string.IsNullOrWhiteSpace(searchPath)) + { + foreach (var dirPath in searchPath.SplitSearchPath()) + { + yield return dirPath; + } + } + + searchPath = HostSettings.AuxiliarySearchPath; + if (!string.IsNullOrWhiteSpace(searchPath)) + { + foreach (var dirPath in searchPath.SplitSearchPath()) + { + yield return dirPath; + } + } + } + + #region IDisposable implementation + + public abstract void Dispose(); + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8Proxy.cs.meta b/Unity/Package/Runtime/V8/V8Proxy.cs.meta new file mode 100644 index 000000000..26b323b82 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Proxy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1eef2649e519b774b9be156de890679a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ProxyHelpers.cs b/Unity/Package/Runtime/V8/V8ProxyHelpers.cs new file mode 100644 index 000000000..a683f534e --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ProxyHelpers.cs @@ -0,0 +1,285 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8 +{ + internal static class V8ProxyHelpers + { + #region host object lifetime + + public static IntPtr AddRefHostObject(IntPtr pObject) + { + return AddRefHostObject(GetHostObject(pObject)); + } + + public static IntPtr AddRefHostObject(object obj) + { + return GCHandle.ToIntPtr(GCHandle.Alloc(obj)); + } + + public static void ReleaseHostObject(IntPtr pObject) + { + GCHandle.FromIntPtr(pObject).Free(); + } + + public static IScope CreateAddRefHostObjectScope(object obj) + { + return Scope.Create(() => AddRefHostObject(obj), ReleaseHostObject); + } + + #endregion + + #region host object access + + public static object GetHostObject(IntPtr pObject) + { + return GCHandle.FromIntPtr(pObject).Target; + } + + public static T GetHostObject(IntPtr pObject) where T : class + { + return (T)GetHostObject(pObject); + } + + public static object GetHostObjectProperty(IntPtr pObject, string name) + { + return GetHostObjectProperty(GetHostObject(pObject), name); + } + + public static object GetHostObjectProperty(object obj, string name) + { + return ((IDynamic)obj).GetProperty(name); + } + + public static object GetHostObjectProperty(IntPtr pObject, string name, out bool isCacheable) + { + return GetHostObjectProperty(GetHostObject(pObject), name, out isCacheable); + } + + public static object GetHostObjectProperty(object obj, string name, out bool isCacheable) + { + return ((IDynamic)obj).GetProperty(name, out isCacheable); + } + + public static void SetHostObjectProperty(IntPtr pObject, string name, object value) + { + SetHostObjectProperty(GetHostObject(pObject), name, value); + } + + public static void SetHostObjectProperty(object obj, string name, object value) + { + ((IDynamic)obj).SetProperty(name, value); + } + + public static bool DeleteHostObjectProperty(IntPtr pObject, string name) + { + return DeleteHostObjectProperty(GetHostObject(pObject), name); + } + + public static bool DeleteHostObjectProperty(object obj, string name) + { + return ((IDynamic)obj).DeleteProperty(name); + } + + public static string[] GetHostObjectPropertyNames(IntPtr pObject) + { + return GetHostObjectPropertyNames(GetHostObject(pObject)); + } + + public static string[] GetHostObjectPropertyNames(object obj) + { + return ((IDynamic)obj).GetPropertyNames(); + } + + public static object GetHostObjectProperty(IntPtr pObject, int index) + { + return GetHostObjectProperty(GetHostObject(pObject), index); + } + + public static object GetHostObjectProperty(object obj, int index) + { + return ((IDynamic)obj).GetProperty(index); + } + + public static void SetHostObjectProperty(IntPtr pObject, int index, object value) + { + SetHostObjectProperty(GetHostObject(pObject), index, value); + } + + public static void SetHostObjectProperty(object obj, int index, object value) + { + ((IDynamic)obj).SetProperty(index, value); + } + + public static bool DeleteHostObjectProperty(IntPtr pObject, int index) + { + return DeleteHostObjectProperty(GetHostObject(pObject), index); + } + + public static bool DeleteHostObjectProperty(object obj, int index) + { + return ((IDynamic)obj).DeleteProperty(index); + } + + public static int[] GetHostObjectPropertyIndices(IntPtr pObject) + { + return GetHostObjectPropertyIndices(GetHostObject(pObject)); + } + + public static int[] GetHostObjectPropertyIndices(object obj) + { + return ((IDynamic)obj).GetPropertyIndices(); + } + + public static object InvokeHostObject(IntPtr pObject, bool asConstructor, object[] args) + { + return InvokeHostObject(GetHostObject(pObject), asConstructor, args); + } + + public static object InvokeHostObject(object obj, bool asConstructor, object[] args) + { + return ((IDynamic)obj).Invoke(asConstructor, args); + } + + public static object InvokeHostObjectMethod(IntPtr pObject, string name, object[] args) + { + return InvokeHostObjectMethod(GetHostObject(pObject), name, args); + } + + public static object InvokeHostObjectMethod(object obj, string name, object[] args) + { + return ((IDynamic)obj).InvokeMethod(name, args); + } + + public static Invocability GetHostObjectInvocability(IntPtr pObject) + { + return GetHostObjectInvocability(GetHostObject(pObject)); + } + + public static Invocability GetHostObjectInvocability(object obj) + { + var hostItem = obj as HostItem; + if (hostItem == null) + { + return Invocability.None; + } + + return hostItem.Invocability; + } + + public static object GetHostObjectEnumerator(IntPtr pObject) + { + return GetHostObjectEnumerator(GetHostObject(pObject)); + } + + public static object GetHostObjectEnumerator(object obj) + { + return ((IDynamic)obj).GetProperty(SpecialMemberNames.NewEnum); + } + + public static object GetHostObjectAsyncEnumerator(IntPtr pObject) + { + return GetHostObjectAsyncEnumerator(GetHostObject(pObject)); + } + + public static object GetHostObjectAsyncEnumerator(object obj) + { + return ((IDynamic)obj).GetProperty(SpecialMemberNames.NewAsyncEnum); + } + + #endregion + + #region exception marshaling + + public static object MarshalExceptionToScript(IntPtr pSource, Exception exception) + { + return MarshalExceptionToScript(GetHostObject(pSource), exception); + } + + public static object MarshalExceptionToScript(object source, Exception exception) + { + return source is IScriptMarshalWrapper scriptMarshalWrapper + ? scriptMarshalWrapper.Engine.MarshalToScript(exception) + : ScriptEngine.Current?.MarshalToScript(exception); + } + + public static Exception MarshalExceptionToHost(object exception) + { + return (Exception)((IScriptMarshalWrapper)exception)?.Engine.MarshalToHost(exception, false); + } + + #endregion + + #region module support + + public static string LoadModule(IntPtr pSourceDocumentInfo, string specifier, out UniqueDocumentInfo documentInfo, out object exports) + { + var engine = ScriptEngine.Current; + if (!(engine is IJavaScriptEngine javaScriptEngine)) + { + throw new InvalidOperationException("Module loading requires a JavaScript engine"); + } + + var document = engine.DocumentSettings.LoadDocument(((UniqueDocumentInfo)GetHostObject(pSourceDocumentInfo)).Info, specifier, ModuleCategory.Standard, null); + var code = document.GetTextContents(); + + documentInfo = document.Info.MakeUnique(engine); + + var category = document.Info.Category; + if (category == ModuleCategory.CommonJS) + { + javaScriptEngine.CommonJSManager.GetOrCreateModule(documentInfo, code).Process(out exports); + } + else if (category == ModuleCategory.Standard) + { + exports = null; + } + else if (category == DocumentCategory.Json) + { + exports = engine.MarshalToScript(javaScriptEngine.JsonModuleManager.GetOrCreateModule(documentInfo, code).Result); + } + else + { + var uri = document.Info.Uri; + var name = (uri != null) ? (uri.IsFile ? uri.LocalPath : uri.AbsoluteUri) : document.Info.Name; + throw new FileLoadException($"Unsupported document category '{category}'", name); + } + + return code; + } + + public static IDictionary CreateModuleContext(IntPtr pDocumentInfo) + { + var engine = ScriptEngine.Current; + if (!(engine is IJavaScriptEngine)) + { + throw new InvalidOperationException("Module context construction requires a JavaScript engine"); + } + + var documentInfo = (UniqueDocumentInfo)GetHostObject(pDocumentInfo); + + var callback = documentInfo.ContextCallback ?? engine.DocumentSettings.ContextCallback; + if ((callback != null) && MiscHelpers.Try(out var sharedContext, () => callback(documentInfo.Info)) && (sharedContext != null)) + { + var context = new Dictionary(sharedContext.Count); + foreach (var pair in sharedContext) + { + context.Add(pair.Key, engine.MarshalToScript(pair.Value)); + } + + return context; + } + + return null; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8ProxyHelpers.cs.meta b/Unity/Package/Runtime/V8/V8ProxyHelpers.cs.meta new file mode 100644 index 000000000..8df53ea04 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ProxyHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 746fe266e037ced4c94b5996760aa92e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8Runtime.cs b/Unity/Package/Runtime/V8/V8Runtime.cs new file mode 100644 index 000000000..8475b6924 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Runtime.cs @@ -0,0 +1,1144 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.IO; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Represents an instance of the V8 runtime. + /// + public sealed class V8Runtime : IDisposable + { + #region data + + private static readonly IUniqueNameManager nameManager = new UniqueNameManager(); + + private DocumentSettings documentSettings; + private readonly DocumentSettings defaultDocumentSettings = new DocumentSettings(); + + private readonly V8IsolateProxy proxy; + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + #endregion + + #region constructors + + /// + /// Initializes a new V8 runtime instance. + /// + public V8Runtime() + : this(null, null) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + public V8Runtime(string name) + : this(name, null) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified resource constraints. + /// + /// Resource constraints for the instance. + public V8Runtime(V8RuntimeConstraints constraints) + : this(null, constraints) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name and resource constraints. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the instance. + public V8Runtime(string name, V8RuntimeConstraints constraints) + : this(name, constraints, V8RuntimeFlags.None) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified options. + /// + /// A value that selects options for the operation. + public V8Runtime(V8RuntimeFlags flags) + : this(flags, 0) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified options and debug port. + /// + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + public V8Runtime(V8RuntimeFlags flags, int debugPort) + : this(null, null, flags, debugPort) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name and options. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + public V8Runtime(string name, V8RuntimeFlags flags) + : this(name, flags, 0) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name, options, and debug port. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + public V8Runtime(string name, V8RuntimeFlags flags, int debugPort) + : this(name, null, flags, debugPort) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified resource constraints and options. + /// + /// Resource constraints for the instance. + /// A value that selects options for the operation. + public V8Runtime(V8RuntimeConstraints constraints, V8RuntimeFlags flags) + : this(constraints, flags, 0) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified resource constraints, options, and debug port. + /// + /// Resource constraints for the instance. + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + public V8Runtime(V8RuntimeConstraints constraints, V8RuntimeFlags flags, int debugPort) + : this(null, constraints, flags, debugPort) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name, resource constraints, and options. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the instance. + /// A value that selects options for the operation. + public V8Runtime(string name, V8RuntimeConstraints constraints, V8RuntimeFlags flags) + : this(name, constraints, flags, 0) + { + } + + /// + /// Initializes a new V8 runtime instance with the specified name, resource constraints, options, and debug port. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the instance. + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + public V8Runtime(string name, V8RuntimeConstraints constraints, V8RuntimeFlags flags, int debugPort) + { + Name = nameManager.GetUniqueName(name, GetType().GetRootName()); + proxy = V8IsolateProxy.Create(Name, constraints, flags, debugPort); + } + + #endregion + + #region public members + + /// + /// Occurs when a debugger connects to a V8 runtime. + /// + public static event EventHandler DebuggerConnected; + + /// + /// Occurs when a debugger disconnects from a V8 runtime. + /// + public static event EventHandler DebuggerDisconnected; + + /// + /// Gets the name associated with the V8 runtime instance. + /// + public string Name { get; } + + /// + /// Enables or disables script code formatting. + /// + /// + /// When this property is set to true, the V8 runtime may format script code before + /// executing or compiling it. This is intended to facilitate interactive debugging. The + /// formatting operation currently includes stripping leading and trailing blank lines and + /// removing global indentation. + /// + public bool FormatCode { get; set; } + + /// + /// Gets or sets a soft limit for the size of the V8 runtime's heap. + /// + /// + /// + /// This property is specified in bytes. When it is set to the default value, heap size + /// monitoring is disabled, and scripts with memory leaks or excessive memory usage + /// can cause unrecoverable errors and process termination. + /// + /// + /// A V8 runtime unconditionally terminates the process when it exceeds its resource + /// constraints (see ). This property enables external + /// heap size monitoring that can prevent termination in some scenarios. To be effective, + /// it should be set to a value that is significantly lower than + /// . Note that enabling heap size + /// monitoring results in slower script execution. + /// + /// + /// Exceeding this limit causes the V8 runtime to behave in accordance with + /// . + /// + /// + /// Note that + /// ArrayBuffer + /// memory is allocated outside the runtime's heap and is therefore not tracked by heap + /// size monitoring. See for + /// additional information. + /// + /// + public UIntPtr MaxHeapSize + { + get + { + VerifyNotDisposed(); + return proxy.MaxHeapSize; + } + + set + { + VerifyNotDisposed(); + proxy.MaxHeapSize = value; + } + } + + /// + /// Gets or sets the minimum time interval between consecutive heap size samples. + /// + /// + /// This property is effective only when heap size monitoring is enabled (see + /// ). + /// + public TimeSpan HeapSizeSampleInterval + { + get + { + VerifyNotDisposed(); + return proxy.HeapSizeSampleInterval; + } + + set + { + VerifyNotDisposed(); + proxy.HeapSizeSampleInterval = value; + } + } + + /// + /// Gets or sets the maximum amount by which the stack is permitted to grow during script execution. + /// + /// + /// + /// This property is specified in bytes. When it is set to the default value, no stack + /// usage limit is enforced, and scripts with unchecked recursion or other excessive stack + /// usage can cause unrecoverable errors and process termination. + /// + /// + /// Note that the V8 runtime does not monitor stack usage while a host call is in progress. + /// Monitoring is resumed when control returns to the runtime. + /// + /// + public UIntPtr MaxStackUsage + { + get + { + VerifyNotDisposed(); + return proxy.MaxStackUsage; + } + + set + { + VerifyNotDisposed(); + proxy.MaxStackUsage = value; + } + } + + /// + /// Gets or sets the V8 runtime's document settings. + /// + public DocumentSettings DocumentSettings + { + get => documentSettings ?? defaultDocumentSettings; + set => documentSettings = value; + } + + /// + /// Enables or disables interrupt propagation in the V8 runtime. + /// + /// + /// By default, when nested script execution is interrupted via + /// , an instance of + /// , if not handled by the host, is wrapped and + /// delivered to the parent script frame as a normal exception that JavaScript code can + /// catch. Setting this property to true causes the V8 runtime to remain in the + /// interrupted state until its outermost script frame has been processed. + /// + public bool EnableInterruptPropagation + { + get + { + VerifyNotDisposed(); + return proxy.EnableInterruptPropagation; + } + + set + { + VerifyNotDisposed(); + proxy.EnableInterruptPropagation = value; + } + } + + /// + /// Gets or sets the V8 runtime's behavior in response to a violation of the maximum heap size. + /// + public V8RuntimeViolationPolicy HeapSizeViolationPolicy + { + get + { + VerifyNotDisposed(); + return proxy.DisableHeapSizeViolationInterrupt ? V8RuntimeViolationPolicy.Exception : V8RuntimeViolationPolicy.Interrupt; + } + + set + { + VerifyNotDisposed(); + switch (value) + { + case V8RuntimeViolationPolicy.Interrupt: + proxy.DisableHeapSizeViolationInterrupt = false; + return; + + case V8RuntimeViolationPolicy.Exception: + proxy.DisableHeapSizeViolationInterrupt = true; + return; + + default: + throw new ArgumentException(MiscHelpers.FormatInvariant("Invalid {0} value", nameof(V8RuntimeViolationPolicy)), nameof(value)); + } + } + } + + /// + /// Creates a new V8 script engine instance. + /// + /// A new V8 script engine instance. + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + public V8ScriptEngine CreateScriptEngine() + { + return CreateScriptEngine(null); + } + + /// + /// Creates a new V8 script engine instance with the specified name. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A new V8 script engine instance. + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + public V8ScriptEngine CreateScriptEngine(string engineName) + { + return CreateScriptEngine(engineName, V8ScriptEngineFlags.None); + } + + /// + /// Creates a new V8 script engine instance with the specified options. + /// + /// A value that selects options for the operation. + /// A new V8 script engine instance. + /// + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + /// + /// V8 supports one script debugger per runtime. If script debugging has been enabled in + /// the current runtime, additional script engine instances cannot disable it or change its + /// TCP port, nor can they enable script debugging on a different port. + /// + /// + public V8ScriptEngine CreateScriptEngine(V8ScriptEngineFlags flags) + { + return CreateScriptEngine(null, flags); + } + + /// + /// Creates a new V8 script engine instance with the specified options and debug port. + /// + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// A new V8 script engine instance. + /// + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + /// + /// V8 supports one script debugger per runtime. If script debugging has been enabled in + /// the current runtime, additional script engine instances cannot disable it or change its + /// TCP port, nor can they enable script debugging on a different port. + /// + /// + public V8ScriptEngine CreateScriptEngine(V8ScriptEngineFlags flags, int debugPort) + { + return CreateScriptEngine(null, flags, debugPort); + } + + /// + /// Creates a new V8 script engine instance with the specified name and options. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + /// A new V8 script engine instance. + /// + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + /// + /// V8 supports one script debugger per runtime. If script debugging has been enabled in + /// the current runtime, additional script engine instances cannot disable it or change its + /// TCP port, nor can they enable script debugging on a different port. + /// + /// + public V8ScriptEngine CreateScriptEngine(string engineName, V8ScriptEngineFlags flags) + { + return CreateScriptEngine(engineName, flags, 0); + } + + /// + /// Creates a new V8 script engine instance with the specified name, options, and debug port. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// A new V8 script engine instance. + /// + /// + /// The new script engine instance shares the V8 runtime with other instances created by + /// this method and any of its overloads. + /// + /// + /// V8 supports one script debugger per runtime. If script debugging has been enabled in + /// the current runtime, additional script engine instances cannot disable it or change its + /// TCP port, nor can they enable script debugging on a different port. + /// + /// + public V8ScriptEngine CreateScriptEngine(string engineName, V8ScriptEngineFlags flags, int debugPort) + { + VerifyNotDisposed(); + return new V8ScriptEngine(this, engineName, null, flags, debugPort) { FormatCode = FormatCode }; + } + + /// + /// Creates a compiled script. + /// + /// The script code to compile. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script Compile(string code) + { + return Compile(null, code); + } + + /// + /// Creates a compiled script with an associated document name. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script Compile(string documentName, string code) + { + return Compile(new DocumentInfo(documentName), code); + } + + /// + /// Creates a compiled script with the specified document meta-information. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script Compile(DocumentInfo documentInfo, string code) + { + VerifyNotDisposed(); + return CompileInternal(documentInfo.MakeUnique(DocumentNameManager), code); + } + + /// + /// Creates a compiled script, generating cache data for accelerated recompilation. + /// + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + /// + public V8Script Compile(string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return Compile(null, code, cacheKind, out cacheBytes); + } + + /// + /// Creates a compiled script with an associated document name, generating cache data for accelerated recompilation. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, out cacheBytes); + } + + /// + /// Creates a compiled script with the specified document meta-information, generating cache data for accelerated recompilation. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + VerifyNotDisposed(); + return CompileInternal(documentInfo.MakeUnique(DocumentNameManager), code, cacheKind, out cacheBytes); + } + + /// + /// Creates a compiled script, consuming previously generated cache data. + /// + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return Compile(null, code, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Creates a compiled script with an associated document name, consuming previously generated cache data. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Creates a compiled script with the specified document meta-information, consuming previously generated cache data. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + VerifyNotDisposed(); + return CompileInternal(documentInfo.MakeUnique(DocumentNameManager), code, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Creates a compiled script, consuming previously generated cache data and updating it if necessary. + /// + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return Compile(null, code, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Creates a compiled script with an associated document name, consuming previously generated cache data and updating it if necessary. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Creates a compiled script with the specified document meta-information, consuming previously generated cache data and updating it if necessary. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + VerifyNotDisposed(); + return CompileInternal(documentInfo.MakeUnique(DocumentNameManager), code, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Loads and compiles a script document. + /// + /// A string specifying the document to be loaded and compiled. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier) + { + return CompileDocument(specifier, null); + } + + /// + /// Loads and compiles a document with the specified category. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier, DocumentCategory category) + { + return CompileDocument(specifier, category, null); + } + + /// + /// Loads and compiles a document with the specified category and context callback. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents()); + } + + /// + /// Loads and compiles a script document, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return CompileDocument(specifier, null, cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a document with the specified category, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return CompileDocument(specifier, category, null, cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a document with the specified category and context callback, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, out byte[] cacheBytes) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a script document, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return CompileDocument(specifier, null, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a document with the specified category, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return CompileDocument(specifier, category, null, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a document with the specified category and context callback, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a script document, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return CompileDocument(specifier, null, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Loads and compiles a document with the specified category, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return CompileDocument(specifier, category, null, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Loads and compiles a document with the specified category and context callback, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Returns memory usage information. + /// + /// A object containing memory usage information. + public V8RuntimeHeapInfo GetHeapInfo() + { + VerifyNotDisposed(); + return proxy.GetHeapInfo(); + } + + /// + /// Performs garbage collection. + /// + /// True to perform exhaustive garbage collection, false to favor speed over completeness. + public void CollectGarbage(bool exhaustive) + { + VerifyNotDisposed(); + proxy.CollectGarbage(exhaustive); + } + + /// + /// Begins collecting a new CPU profile. + /// + /// A name for the profile. + /// True if the profile was created successfully, false otherwise. + /// + /// A V8 runtime can collect multiple CPU profiles simultaneously. + /// + public bool BeginCpuProfile(string name) + { + return BeginCpuProfile(name, V8CpuProfileFlags.None); + } + + /// + /// Begins collecting a new CPU profile with the specified options. + /// + /// A name for the profile. + /// Options for creating the profile. + /// True if the profile was created successfully, false otherwise. + /// + /// A V8 runtime can collect multiple CPU profiles simultaneously. + /// + public bool BeginCpuProfile(string name, V8CpuProfileFlags flags) + { + VerifyNotDisposed(); + return proxy.BeginCpuProfile(name, flags); + } + + /// + /// Completes and returns a CPU profile. + /// + /// The name of the profile. + /// The profile if it was found and completed successfully, null otherwise. + /// + /// An empty argument selects the most recently created CPU profile. + /// + public V8CpuProfile EndCpuProfile(string name) + { + VerifyNotDisposed(); + return proxy.EndCpuProfile(name); + } + + /// + /// Collects a sample in all CPU profiles active in the V8 runtime. + /// + public void CollectCpuProfileSample() + { + VerifyNotDisposed(); + proxy.CollectCpuProfileSample(); + } + + /// + /// Gets or sets the time interval between automatic CPU profile samples, in microseconds. + /// + /// + /// Assigning this property has no effect on CPU profiles already active in the V8 runtime. + /// The default value is 1000. + /// + public uint CpuProfileSampleInterval + { + get + { + VerifyNotDisposed(); + return proxy.CpuProfileSampleInterval; + } + + set + { + VerifyNotDisposed(); + proxy.CpuProfileSampleInterval = value; + } + } + + /// + /// Writes a heap snapshot to the given stream. + /// + /// The stream to which to write the heap snapshot. + /// + /// This method generates a heap snapshot in JSON format with ASCII encoding. + /// + public void WriteHeapSnapshot(Stream stream) + { + MiscHelpers.VerifyNonNullArgument(stream, nameof(stream)); + VerifyNotDisposed(); + + using (var engine = CreateScriptEngine(Name)) + { + engine.ScriptInvoke(() => proxy.WriteHeapSnapshot(stream)); + } + } + + #endregion + + #region internal members + + internal readonly UniqueFileNameManager DocumentNameManager = new UniqueFileNameManager(); + + internal readonly HostItemCollateral HostItemCollateral = new HostItemCollateral(); + + internal static void OnDebuggerConnected(V8RuntimeDebuggerEventArgs args) + { + DebuggerConnected?.Invoke(null, args); + } + + internal static void OnDebuggerDisconnected(V8RuntimeDebuggerEventArgs args) + { + DebuggerDisconnected?.Invoke(null, args); + } + + internal V8IsolateProxy IsolateProxy + { + get + { + VerifyNotDisposed(); + return proxy; + } + } + + internal Statistics GetStatistics() + { + VerifyNotDisposed(); + return proxy.GetStatistics(); + } + + private void VerifyNotDisposed() + { + if (disposedFlag.IsSet) + { + throw new ObjectDisposedException(ToString()); + } + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + if (documentInfo.Category == ModuleCategory.CommonJS) + { + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The V8 runtime cannot compile documents of type '" + documentInfo.Category + "'"); + } + + return proxy.Compile(documentInfo, code); + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + if (documentInfo.Category == ModuleCategory.CommonJS) + { + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The V8 runtime cannot compile documents of type '" + documentInfo.Category + "'"); + } + + return proxy.Compile(documentInfo, code, cacheKind, out cacheBytes); + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + if (documentInfo.Category == ModuleCategory.CommonJS) + { + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The V8 runtime cannot compile documents of type '" + documentInfo.Category + "'"); + } + + return proxy.Compile(documentInfo, code, cacheKind, cacheBytes, out cacheAccepted); + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + if (documentInfo.Category == ModuleCategory.CommonJS) + { + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The V8 runtime cannot compile documents of type '" + documentInfo.Category + "'"); + } + + return proxy.Compile(documentInfo, code, cacheKind, ref cacheBytes, out cacheResult); + } + + #endregion + + #region IDisposable implementation + + /// + public void Dispose() + { + if (disposedFlag.Set()) + { + proxy.Dispose(); + } + } + + #endregion + + #region Nested type: TaskKind + + internal enum TaskKind : ushort + { + Worker, + DelayedWorker, + Foreground, + DelayedForeground, + NonNestableForeground, + NonNestableDelayedForeground, + Count + } + + #endregion + + #region Nested type: Statistics + + internal sealed class Statistics + { + public ulong ScriptCount; + public ulong ScriptCacheSize; + public ulong ModuleCount; + public ulong[] PostedTaskCounts; + public ulong[] InvokedTaskCounts; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8Runtime.cs.meta b/Unity/Package/Runtime/V8/V8Runtime.cs.meta new file mode 100644 index 000000000..b37abc2bb --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Runtime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fccda07804fb2bc4aa8620b032c18ce8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs b/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs new file mode 100644 index 000000000..699986c20 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Specifies resource constraints for a V8 runtime. + /// + public sealed class V8RuntimeConstraints + { + // ReSharper disable EmptyConstructor + + /// + /// Initializes a new instance. + /// + public V8RuntimeConstraints() + { + // the help file builder (SHFB) insists on an empty constructor here + } + + // ReSharper restore EmptyConstructor + + /// + /// Gets or sets the maximum size of the new object heap in + /// MiB. + /// + /// + /// For maximum compatibility with hosts that predate an inadvertent breaking change in + /// ClearScript 5.4.1, values greater than 1048576 + /// (1 TiB) are assumed to be in + /// bytes rather than MiB. For example, the values 16 and 16777216 both specify a limit + /// of 16 MiB. + /// + public int MaxNewSpaceSize { get; set; } + + /// + /// Gets or sets the maximum size of the old object heap in + /// MiB. + /// + /// + /// For maximum compatibility with hosts that predate an inadvertent breaking change in + /// ClearScript 5.4.1, values greater than 1048576 + /// (1 TiB) are assumed to be in + /// bytes rather than MiB. For example, the values 16 and 16777216 both specify a limit + /// of 16 MiB. + /// + public int MaxOldSpaceSize { get; set; } + + /// + /// Gets or sets the maximum size of the executable code heap in + /// MiB. + /// + /// + /// For maximum compatibility with hosts that predate an inadvertent breaking change in + /// ClearScript 5.4.1, values greater than 1048576 + /// (1 TiB) are assumed to be in + /// bytes rather than MiB. For example, the values 16 and 16777216 both specify a limit + /// of 16 MiB. + /// + [Obsolete("Executable code now occupies the old object heap. See MaxOldSpaceSize.")] + public int MaxExecutableSize { get; set; } + + /// + /// Gets or sets the maximum size of the young object heap in + /// MiB. + /// + /// + /// For maximum compatibility with hosts that predate an inadvertent breaking change in + /// ClearScript 5.4.1, values greater than 1048576 + /// (1 TiB) are assumed to be in + /// bytes rather than MiB. For example, the values 16 and 16777216 both specify a limit + /// of 16 MiB. + /// + [Obsolete("Use MaxNewSpaceSize instead.")] + public int MaxYoungSpaceSize + { + get => MaxNewSpaceSize; + set => MaxNewSpaceSize = value; + } + + /// + /// Gets or sets the heap expansion multiplier. + /// + /// + /// When set to a value greater than 1, this property enables on-demand heap expansion, + /// which automatically increases the maximum heap size by the specified multiplier + /// whenever the script engine is close to exceeding the current limit. Note that a buggy + /// or malicious script can still cause an application to fail by exhausting its address + /// space or total available memory. On-demand heap expansion is recommended for use in + /// conjunction with heap size monitoring (see , + /// ) to help contain runaway scripts. + /// + public double HeapExpansionMultiplier { get; set; } + + /// + /// Gets or sets the maximum amount of + /// ArrayBuffer + /// memory the runtime may allocate. + /// + /// + /// This property is specified in bytes. ArrayBuffer memory is allocated outside the + /// runtime's heap and released when its garbage collector reclaims the corresponding + /// JavaScript ArrayBuffer object. Leave this property at its default value to + /// enforce no limit. + /// + public ulong MaxArrayBufferAllocation { get; set; } = ulong.MaxValue; + } +} diff --git a/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs.meta b/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs.meta new file mode 100644 index 000000000..915e64db3 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeConstraints.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 788363c96a50eb34892a4068657b186a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs b/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs new file mode 100644 index 000000000..15404b266 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Provides data for debugger events associated with V8 runtimes. + /// + public sealed class V8RuntimeDebuggerEventArgs : EventArgs + { + /// + /// Gets the name associated with the V8 runtime instance. + /// + public string Name { get; } + + /// + /// Gets the TCP port of the debugger connection. + /// + public int Port { get; } + + internal V8RuntimeDebuggerEventArgs(string name, int port) + { + Name = name; + Port = port; + } + } +} diff --git a/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs.meta b/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs.meta new file mode 100644 index 000000000..a1ea434ba --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeDebuggerEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef03a2f8f863b2a44bc31442255ff2da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8RuntimeFlags.cs b/Unity/Package/Runtime/V8/V8RuntimeFlags.cs new file mode 100644 index 000000000..613c3951e --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeFlags.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines options for initializing a new V8 runtime instance. + /// + [Flags] + public enum V8RuntimeFlags + { + // IMPORTANT: maintain bitwise equivalence with unmanaged enum V8Isolate::Flags + + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that script debugging features are to be enabled. + /// + EnableDebugging = 0x00000001, + + /// + /// Specifies that remote script debugging is to be enabled. This option is ignored if + /// is not specified. + /// + EnableRemoteDebugging = 0x00000002, + + /// + /// Specifies that + /// dynamic module imports + /// are to be enabled. This is an experimental feature and may be removed in a future release. + /// + EnableDynamicModuleImports = 0x00000004 + } +} diff --git a/Unity/Package/Runtime/V8/V8RuntimeFlags.cs.meta b/Unity/Package/Runtime/V8/V8RuntimeFlags.cs.meta new file mode 100644 index 000000000..a888740f5 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5442313c521783143a05603a829922fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs b/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs new file mode 100644 index 000000000..c4f6524e0 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Contains memory usage information for a V8 runtime. + /// + public class V8RuntimeHeapInfo + { + internal V8RuntimeHeapInfo() + { + } + + /// + /// Gets the total heap size in bytes. + /// + public ulong TotalHeapSize { get; internal set; } + + /// + /// Gets the total executable heap size in bytes. + /// + public ulong TotalHeapSizeExecutable { get; internal set; } + + /// + /// Gets the total physical memory size in bytes. + /// + public ulong TotalPhysicalSize { get; internal set; } + + /// + /// Gets the total available memory size in bytes. + /// + public ulong TotalAvailableSize { get; internal set; } + + /// + /// Gets the used heap size in bytes. + /// + public ulong UsedHeapSize { get; internal set; } + + /// + /// Gets the heap size limit in bytes. + /// + public ulong HeapSizeLimit { get; internal set; } + + /// + /// Gets the total external memory size in bytes. + /// + public ulong TotalExternalSize { get; internal set; } + } +} diff --git a/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs.meta b/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs.meta new file mode 100644 index 000000000..1c4bde7fc --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeHeapInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f0ab0e5a8f48274f955193f66f3d70d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs b/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs new file mode 100644 index 000000000..e7fdd3026 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines options for V8 runtime behavior in response to a violation. + /// + /// + /// + public enum V8RuntimeViolationPolicy + { + /// + /// Specifies that the runtime is to interrupt script execution and throw a managed + /// exception. Additionally, further script execution is to be blocked until the host sets + /// the exceeded limit to a new value. This is the default behavior and the most effective + /// option for preventing process termination. + /// + Interrupt, + + /// + /// Specifies that the runtime is to throw a script exception and disable monitoring until + /// the host sets the exceeded limit to a new value. This option is less effective at + /// preventing process termination than , but it is more friendly to + /// asynchronous JavaScript, which relies on post-error processing for mechanisms such as + /// promise + /// rejection. + /// + Exception + } +} diff --git a/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs.meta b/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs.meta new file mode 100644 index 000000000..653a26262 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8RuntimeViolationPolicy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc9fe72302aed114a8e4c4330889bc0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8Script.cs b/Unity/Package/Runtime/V8/V8Script.cs new file mode 100644 index 000000000..2ba12db84 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Script.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Represents a compiled script that can be executed multiple times without recompilation. + /// + public abstract class V8Script : IDisposable + { + internal V8Script(UniqueDocumentInfo documentInfo, UIntPtr codeDigest) + { + UniqueDocumentInfo = documentInfo; + CodeDigest = codeDigest; + } + + /// + /// Gets the document name associated with the compiled script. + /// + [Obsolete("Use DocumentInfo instead.")] + public string Name => UniqueDocumentInfo.UniqueName; + + /// + /// Gets the document meta-information for the compiled script. + /// + public DocumentInfo DocumentInfo => UniqueDocumentInfo.Info; + + internal UniqueDocumentInfo UniqueDocumentInfo { get; } + + internal UIntPtr CodeDigest { get; } + + #region IDisposable implementation + + /// + /// Releases all resources used by the compiled script. + /// + /// + /// Call Dispose() when you are finished using the compiled script. Dispose() + /// leaves the compiled script in an unusable state. After calling Dispose(), you + /// must release all references to the compiled script so the garbage collector can reclaim + /// the memory that the compiled script was occupying. + /// + [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "This class is almost purely abstract; the implementation class implements disposal.")] + public abstract void Dispose(); + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8Script.cs.meta b/Unity/Package/Runtime/V8/V8Script.cs.meta new file mode 100644 index 000000000..0a11a05f3 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Script.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dddbd31b56a85184296e812bae7a52ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs b/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs new file mode 100644 index 000000000..3017ae449 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + + + + +namespace Microsoft.ClearScript.V8 +{ + public sealed partial class V8ScriptEngine + { + private const string initScript = "Object.defineProperty(this,'EngineInternal',{value:(t=>{let e=t=>t.bind();function r(){return new this(...arguments)}let o=t.isHostObjectKey;delete t.isHostObjectKey;let n=t=>!!t&&!0===t[o],c=Promise,i=JSON,a=Symbol(),s=t.toJson;return delete t.toJson,Object.freeze({commandHolder:{},getCommandResult:e(t=>null==t?t:'function'!=typeof t.hasOwnProperty?'Module'===t[Symbol.toStringTag]?'[module]':'[external]':!0===t[o]?t:'function'!=typeof t.toString?'['+typeof t+']':t.toString()),strictEquals:e((t,e)=>t===e),invokeConstructor:e((t,e)=>{if('function'!=typeof t)throw Error('Function expected');return r.apply(t,Array.from(e))}),invokeMethod:e((t,e,r)=>{if('function'!=typeof e)throw Error('Function expected');return e.apply(t,Array.from(r))}),createPromise:e(function(){return new c(...arguments)}),isPromise:e(t=>t instanceof c),isHostObject:e(n),completePromiseWithResult:e((t,e,r)=>{try{e(t())}catch(o){r(o)}}),completePromise:e((t,e,r)=>{try{t(),e()}catch(o){r(o)}}),throwValue:e(t=>{throw t}),getStackTrace:e(()=>{try{throw Error('[stack trace]')}catch(t){return t.stack}}),toIterator:e(function*(t){try{for(;t.ScriptableMoveNext();)yield t.ScriptableCurrent}finally{t.ScriptableDispose()}}),toAsyncIterator:e(async function*(t){try{for(;await t.ScriptableMoveNextAsync();)yield t.ScriptableCurrent}finally{await t.ScriptableDisposeAsync()}}),getIterator:e(t=>t?.[Symbol.iterator]?.()),getAsyncIterator:e(t=>t?.[Symbol.asyncIterator]?.()),checkpoint:e(()=>{let e=t[a];if(e)throw e}),toJson:e((t,e)=>s?i.parse(s(t,e)):e),parseJson:e(t=>i.parse(t)),asyncGenerator:async function*(){}().constructor})})(this)});"; + } +} diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs.meta b/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs.meta new file mode 100644 index 000000000..6a0c4d118 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.InitScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b1bc261bfcbc1a4a85060f19f4845f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs b/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs new file mode 100644 index 000000000..858553c26 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; + +namespace Microsoft.ClearScript.V8 +{ + public sealed partial class V8ScriptEngine + { + #region internal members + + private void CompletePromise(ValueTask valueTask, object resolve, object reject) + { + Func getResult = () => valueTask.Result; + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + engineInternal.InvokeMethod("completePromiseWithResult", getResult, resolve, reject); + } + + private void CompletePromise(ValueTask valueTask, object resolve, object reject) + { + Action wait = () => WaitForValueTask(valueTask); + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + engineInternal.InvokeMethod("completePromise", wait, resolve, reject); + } + + private static void WaitForValueTask(ValueTask valueTask) + { + if (valueTask.IsCompletedSuccessfully) + { + return; + } + + if (valueTask.IsCanceled) + { + throw new TaskCanceledException(); + } + + valueTask.AsTask().Wait(); + } + + partial void TryConvertValueTaskToPromise(object obj, Action setResult) + { + if (obj.GetType().IsAssignableToGenericType(typeof(ValueTask<>), out var typeArgs)) + { + setResult(typeof(ValueTaskConverter<>).MakeSpecificType(typeArgs).InvokeMember("ToPromise", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new[] { obj, this })); + } + else if (obj is ValueTask valueTask) + { + setResult(valueTask.ToPromise(this)); + } + } + + #endregion + + #region IJavaScriptEngine implementation + + object IJavaScriptEngine.CreatePromiseForValueTask(ValueTask valueTask) + { + if (valueTask.IsCompleted) + { + return CreatePromise((resolve, reject) => CompletePromise(valueTask, resolve, reject)); + } + + return ((IJavaScriptEngine)this).CreatePromiseForTask(valueTask.AsTask()); + } + + object IJavaScriptEngine.CreatePromiseForValueTask(ValueTask valueTask) + { + if (valueTask.IsCompleted) + { + return CreatePromise((resolve, reject) => CompletePromise(valueTask, resolve, reject)); + } + + return ((IJavaScriptEngine)this).CreatePromiseForTask(valueTask.AsTask()); + } + + #endregion + + #region Nested type: ValueTaskConverter + + private static class ValueTaskConverter + { + // ReSharper disable UnusedMember.Local + + public static object ToPromise(ValueTask valueTask, V8ScriptEngine engine) + { + return valueTask.ToPromise(engine); + } + + // ReSharper restore UnusedMember.Local + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs.meta b/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs.meta new file mode 100644 index 000000000..3d8343282 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.NetStandard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f31fb96a0377128489cdffd0eb6ae264 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.cs b/Unity/Package/Runtime/V8/V8ScriptEngine.cs new file mode 100644 index 000000000..80850ab21 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.cs @@ -0,0 +1,1959 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; +using Newtonsoft.Json; + +namespace Microsoft.ClearScript.V8 +{ + // ReSharper disable once PartialTypeWithSinglePart + + /// + /// Represents an instance of the V8 JavaScript engine. + /// + /// + /// Unlike WindowsScriptEngine instances, V8ScriptEngine instances do not have + /// thread affinity. The underlying script engine is not thread-safe, however, so this class + /// uses internal locks to automatically serialize all script code execution for a given + /// instance. Script delegates and event handlers are invoked on the calling thread without + /// marshaling. + /// + public sealed partial class V8ScriptEngine : ScriptEngine, IJavaScriptEngine + { + #region data + + private static readonly DocumentInfo initScriptInfo = new DocumentInfo(MiscHelpers.FormatInvariant("{0} [internal]", nameof(V8ScriptEngine))); + + private readonly V8Runtime runtime; + private readonly bool usingPrivateRuntime; + + private readonly V8ScriptEngineFlags engineFlags; + private readonly V8ContextProxy proxy; + private readonly V8ScriptItem script; + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + private const int continuationInterval = 2000; + private bool inContinuationTimerScope; + private bool? awaitDebuggerAndPause; + + private List documentNames; + private bool suppressInstanceMethodEnumeration; + private bool suppressExtensionMethodEnumeration; + + private CommonJSManager commonJSManager; + private JsonModuleManager jsonDocumentManager; + + #endregion + + #region constructors + + /// + /// Initializes a new V8 script engine instance. + /// + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine() + : this(null, null) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name) + : this(name, null) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified resource constraints. + /// + /// Resource constraints for the V8 runtime (see remarks). + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(V8RuntimeConstraints constraints) + : this(null, constraints) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name and resource constraints. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the V8 runtime (see remarks). + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name, V8RuntimeConstraints constraints) + : this(name, constraints, V8ScriptEngineFlags.None) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified options. + /// + /// A value that selects options for the operation. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(V8ScriptEngineFlags flags) + : this(flags, 0) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified options and debug port. + /// + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(V8ScriptEngineFlags flags, int debugPort) + : this(null, null, flags, debugPort) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name and options. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name, V8ScriptEngineFlags flags) + : this(name, flags, 0) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name, options, and debug port. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name, V8ScriptEngineFlags flags, int debugPort) + : this(name, null, flags, debugPort) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified resource constraints and options. + /// + /// Resource constraints for the V8 runtime (see remarks). + /// A value that selects options for the operation. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(V8RuntimeConstraints constraints, V8ScriptEngineFlags flags) + : this(constraints, flags, 0) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified resource constraints, options, and debug port. + /// + /// Resource constraints for the V8 runtime (see remarks). + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(V8RuntimeConstraints constraints, V8ScriptEngineFlags flags, int debugPort) + : this(null, constraints, flags, debugPort) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name, resource constraints, and options. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the V8 runtime (see remarks). + /// A value that selects options for the operation. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name, V8RuntimeConstraints constraints, V8ScriptEngineFlags flags) + : this(name, constraints, flags, 0) + { + } + + /// + /// Initializes a new V8 script engine instance with the specified name, resource constraints, options, and debug port. + /// + /// A name to associate with the instance. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// Resource constraints for the V8 runtime (see remarks). + /// A value that selects options for the operation. + /// A TCP port on which to listen for a debugger connection. + /// + /// A separate V8 runtime is created for the new script engine instance. + /// + public V8ScriptEngine(string name, V8RuntimeConstraints constraints, V8ScriptEngineFlags flags, int debugPort) + : this(null, name, constraints, flags, debugPort) + { + } + + internal V8ScriptEngine(V8Runtime runtime, string name, V8RuntimeConstraints constraints, V8ScriptEngineFlags flags, int debugPort) + : base((runtime != null) ? runtime.Name + ":" + name : name, "js") + { + if (runtime != null) + { + this.runtime = runtime; + } + else + { + this.runtime = runtime = new V8Runtime(name, constraints); + usingPrivateRuntime = true; + } + + DocumentNameManager = runtime.DocumentNameManager; + HostItemCollateral = runtime.HostItemCollateral; + + engineFlags = flags; + proxy = V8ContextProxy.Create(runtime.IsolateProxy, Name, flags, debugPort); + script = (V8ScriptItem)GetRootItem(); + + if (flags.HasFlag(V8ScriptEngineFlags.EnableStringifyEnhancements)) + { + script.SetProperty("toJson", new Func(new JsonHelper(this).ToJson)); + } + + Execute(initScriptInfo, initScript); + + if (flags.HasFlag(V8ScriptEngineFlags.EnableDebugging | V8ScriptEngineFlags.AwaitDebuggerAndPauseOnStart)) + { + awaitDebuggerAndPause = true; + } + } + + #endregion + + #region public members + + /// + /// Resumes script execution if the script engine is waiting for a debugger connection. + /// + /// + /// This method can be called safely from any thread. + /// + public void CancelAwaitDebugger() + { + VerifyNotDisposed(); + proxy.CancelAwaitDebugger(); + } + + /// + /// Gets or sets a soft limit for the size of the V8 runtime's heap. + /// + /// + /// + /// This property is specified in bytes. When it is set to the default value, heap size + /// monitoring is disabled, and scripts with memory leaks or excessive memory usage + /// can cause unrecoverable errors and process termination. + /// + /// + /// A V8 runtime unconditionally terminates the process when it exceeds its resource + /// constraints (see ). This property enables external + /// heap size monitoring that can prevent termination in some scenarios. To be effective, + /// it should be set to a value that is significantly lower than + /// . Note that enabling heap size + /// monitoring results in slower script execution. + /// + /// + /// Exceeding this limit causes the V8 runtime to behave in accordance with + /// . + /// + /// + /// Note that + /// ArrayBuffer + /// memory is allocated outside the runtime's heap and is therefore not tracked by heap + /// size monitoring. See for + /// additional information. + /// + /// + public UIntPtr MaxRuntimeHeapSize + { + get + { + VerifyNotDisposed(); + return proxy.MaxIsolateHeapSize; + } + + set + { + VerifyNotDisposed(); + proxy.MaxIsolateHeapSize = value; + } + } + + /// + /// Gets or sets the minimum time interval between consecutive heap size samples. + /// + /// + /// This property is effective only when heap size monitoring is enabled (see + /// ). + /// + public TimeSpan RuntimeHeapSizeSampleInterval + { + get + { + VerifyNotDisposed(); + return proxy.IsolateHeapSizeSampleInterval; + } + + set + { + VerifyNotDisposed(); + proxy.IsolateHeapSizeSampleInterval = value; + } + } + + /// + /// Gets or sets the maximum amount by which the V8 runtime is permitted to grow the stack during script execution. + /// + /// + /// + /// This property is specified in bytes. When it is set to the default value, no stack + /// usage limit is enforced, and scripts with unchecked recursion or other excessive stack + /// usage can cause unrecoverable errors and process termination. + /// + /// + /// Note that the V8 runtime does not monitor stack usage while a host call is in progress. + /// Monitoring is resumed when control returns to the runtime. + /// + /// + public UIntPtr MaxRuntimeStackUsage + { + get + { + VerifyNotDisposed(); + return proxy.MaxIsolateStackUsage; + } + + set + { + VerifyNotDisposed(); + proxy.MaxIsolateStackUsage = value; + } + } + + /// + /// Enables or disables instance method enumeration. + /// + /// + /// By default, a host object's instance methods are exposed as enumerable properties. + /// Setting this property to true causes instance methods to be excluded from + /// property enumeration. This affects all host objects exposed in the current script + /// engine. Note that instance methods remain both retrievable and invocable regardless of + /// this property's value. + /// + public bool SuppressInstanceMethodEnumeration + { + get => suppressInstanceMethodEnumeration; + + set + { + suppressInstanceMethodEnumeration = value; + OnEnumerationSettingsChanged(); + } + } + + /// + /// Enables or disables extension method enumeration. + /// + /// + /// + /// By default, all exposed extension methods appear as enumerable properties of all host + /// objects, regardless of type. Setting this property to true causes extension + /// methods to be excluded from property enumeration. This affects all host objects exposed + /// in the current script engine. Note that extension methods remain both retrievable and + /// invocable regardless of this property's value. + /// + /// + /// This property has no effect if is set + /// to true. + /// + /// + public bool SuppressExtensionMethodEnumeration + { + get => suppressExtensionMethodEnumeration; + + set + { + suppressExtensionMethodEnumeration = value; + RebuildExtensionMethodSummary(); + } + } + + /// + /// Enables or disables interrupt propagation in the V8 runtime. + /// + /// + /// By default, when nested script execution is interrupted via , an + /// instance of , if not handled by the host, is + /// wrapped and delivered to the parent script frame as a normal exception that JavaScript + /// code can catch. Setting this property to true causes the V8 runtime to remain in + /// the interrupted state until its outermost script frame has been processed. + /// + public bool EnableRuntimeInterruptPropagation + { + get + { + VerifyNotDisposed(); + return proxy.EnableIsolateInterruptPropagation; + } + + set + { + VerifyNotDisposed(); + proxy.EnableIsolateInterruptPropagation = value; + } + } + + /// + /// Gets or sets the V8 runtime's behavior in response to a violation of the maximum heap size. + /// + public V8RuntimeViolationPolicy RuntimeHeapSizeViolationPolicy + { + get + { + VerifyNotDisposed(); + return proxy.DisableIsolateHeapSizeViolationInterrupt ? V8RuntimeViolationPolicy.Exception : V8RuntimeViolationPolicy.Interrupt; + } + + set + { + VerifyNotDisposed(); + switch (value) + { + case V8RuntimeViolationPolicy.Interrupt: + proxy.DisableIsolateHeapSizeViolationInterrupt = false; + return; + + case V8RuntimeViolationPolicy.Exception: + proxy.DisableIsolateHeapSizeViolationInterrupt = true; + return; + + default: + throw new ArgumentException(MiscHelpers.FormatInvariant("Invalid {0} value", nameof(V8RuntimeViolationPolicy)), nameof(value)); + } + } + } + + /// + /// Creates a compiled script. + /// + /// The script code to compile. + /// A compiled script that can be executed multiple times without recompilation. + public V8Script Compile(string code) + { + return Compile(null, code); + } + + /// + /// Creates a compiled script with an associated document name. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// A compiled script that can be executed multiple times without recompilation. + public V8Script Compile(string documentName, string code) + { + return Compile(new DocumentInfo(documentName), code); + } + + /// + /// Creates a compiled script with the specified document meta-information. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// A compiled script that can be executed multiple times without recompilation. + public V8Script Compile(DocumentInfo documentInfo, string code) + { + VerifyNotDisposed(); + return ScriptInvoke(() => CompileInternal(documentInfo.MakeUnique(this), code)); + } + + /// + /// Creates a compiled script, generating cache data for accelerated recompilation. + /// + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// The generated cache data can be stored externally and is usable in other V8 script + /// engines and application processes. + /// + /// + public V8Script Compile(string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return Compile(null, code, cacheKind, out cacheBytes); + } + + /// + /// Creates a compiled script with an associated document name, generating cache data for accelerated recompilation. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// The generated cache data can be stored externally and is usable in other V8 script + /// engines and application processes. + /// + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, out cacheBytes); + } + + /// + /// Creates a compiled script with the specified document meta-information, generating cache data for accelerated recompilation. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// The generated cache data can be stored externally and is usable in other V8 script + /// engines and application processes. + /// + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + VerifyNotDisposed(); + + V8Script tempScript = null; + cacheBytes = ScriptInvoke(() => + { + tempScript = CompileInternal(documentInfo.MakeUnique(this), code, cacheKind, out var tempCacheBytes); + return tempCacheBytes; + }); + + return tempScript; + } + + /// + /// Creates a compiled script, consuming previously generated cache data. + /// + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return Compile(null, code, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Creates a compiled script with an associated document name, consuming previously generated cache data. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Creates a compiled script with an associated document name, consuming previously generated cache data. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + VerifyNotDisposed(); + + V8Script tempScript = null; + cacheAccepted = ScriptInvoke(() => + { + tempScript = CompileInternal(documentInfo.MakeUnique(this), code, cacheKind, cacheBytes, out var tempCacheAccepted); + return tempCacheAccepted; + }); + + return tempScript; + } + + /// + /// Creates a compiled script, consuming previously generated cache data and updating it if necessary. + /// + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return Compile(null, code, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Creates a compiled script with an associated document name, consuming previously generated cache data and updating it if necessary. + /// + /// A document name for the compiled script. Currently, this name is used only as a label in presentation contexts such as debugger user interfaces. + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(string documentName, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return Compile(new DocumentInfo(documentName), code, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Creates a compiled script with the specified document meta-information, consuming previously generated cache data and updating it if necessary. + /// + /// A structure containing meta-information for the script document. + /// The script code to compile. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed multiple times without recompilation. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script Compile(DocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + VerifyNotDisposed(); + + V8Script tempScript = null; + var tempCacheBytes = cacheBytes; + cacheResult = ScriptInvoke(() => + { + tempScript = CompileInternal(documentInfo.MakeUnique(this), code, cacheKind, ref tempCacheBytes, out var tempCacheUpdated); + return tempCacheUpdated; + }); + + if (cacheResult == V8CacheResult.Updated) + { + cacheBytes = tempCacheBytes; + } + + return tempScript; + } + + /// + /// Loads and compiles a script document. + /// + /// A string specifying the document to be loaded and compiled. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier) + { + return CompileDocument(specifier, null); + } + + /// + /// Loads and compiles a document with the specified category. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier, DocumentCategory category) + { + return CompileDocument(specifier, category, null); + } + + /// + /// Loads and compiles a document with the specified category and context callback. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// A compiled script that can be executed by multiple V8 script engine instances. + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents()); + } + + /// + /// Loads and compiles a script document, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return CompileDocument(specifier, null, cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a document with the specified category, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, out byte[] cacheBytes) + { + return CompileDocument(specifier, category, null, cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a document with the specified category and context callback, generating cache data for accelerated recompilation. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be generated. + /// Cache data for accelerated recompilation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// The generated cache data can be stored externally and is usable in other V8 runtimes + /// and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, out byte[] cacheBytes) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, out cacheBytes); + } + + /// + /// Loads and compiles a script document, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return CompileDocument(specifier, null, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a document with the specified category, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + return CompileDocument(specifier, category, null, cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a document with the specified category and context callback, consuming previously generated cache data. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be consumed. + /// Cache data for accelerated compilation. + /// True if was accepted and used to accelerate script compilation, false otherwise. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. Note that script compilation may be bypassed if a suitable compiled + /// script already exists in the V8 runtime's memory. In that case, the cache data is + /// ignored and is set to false. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, cacheBytes, out cacheAccepted); + } + + /// + /// Loads and compiles a script document, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return CompileDocument(specifier, null, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Loads and compiles a document with the specified category, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + return CompileDocument(specifier, category, null, cacheKind, ref cacheBytes, out cacheResult); + } + + /// + /// Loads and compiles a document with the specified category and context callback, consuming previously generated cache data and updating it if necessary. + /// + /// A string specifying the document to be loaded and compiled. + /// An optional category for the requested document. + /// An optional context callback for the requested document. + /// The kind of cache data to be processed. + /// Cache data for accelerated compilation. + /// The cache data processing result for the operation. + /// A compiled script that can be executed by multiple V8 script engine instances. + /// + /// To be accepted, the cache data must have been generated for identical script code by + /// the same V8 build. If returned, the updated cache data can be stored externally and is + /// usable in other V8 script engines and application processes. + /// + public V8Script CompileDocument(string specifier, DocumentCategory category, DocumentContextCallback contextCallback, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + MiscHelpers.VerifyNonBlankArgument(specifier, nameof(specifier), "Invalid document specifier"); + var document = DocumentSettings.LoadDocument(null, specifier, category, contextCallback); + return Compile(document.Info, document.GetTextContents(), cacheKind, ref cacheBytes, out cacheResult); + } + + // ReSharper disable ParameterHidesMember + + /// + /// Evaluates a compiled script. + /// + /// The compiled script to evaluate. + /// The result value. + /// + /// For information about the types of result values that script code can return, see + /// . + /// + public object Evaluate(V8Script script) + { + return Execute(script, true); + } + + /// + /// Executes a compiled script. + /// + /// The compiled script to execute. + /// + /// This method is similar to with the exception that it + /// does not marshal a result value to the host. It can provide a performance advantage + /// when the result value is not needed. + /// + public void Execute(V8Script script) + { + Execute(script, false); + } + + // ReSharper restore ParameterHidesMember + + /// + /// Cancels any pending request to interrupt script execution. + /// + /// + /// This method can be called safely from any thread. + /// + /// + public void CancelInterrupt() + { + VerifyNotDisposed(); + proxy.CancelInterrupt(); + } + + /// + /// Returns memory usage information for the V8 runtime. + /// + /// A object containing memory usage information for the V8 runtime. + public V8RuntimeHeapInfo GetRuntimeHeapInfo() + { + VerifyNotDisposed(); + return proxy.GetIsolateHeapInfo(); + } + + /// + /// Begins collecting a new CPU profile. + /// + /// A name for the profile. + /// True if the profile was created successfully, false otherwise. + /// + /// A V8 script engine can collect multiple CPU profiles simultaneously. + /// + public bool BeginCpuProfile(string name) + { + return BeginCpuProfile(name, V8CpuProfileFlags.None); + } + + /// + /// Begins collecting a new CPU profile with the specified options. + /// + /// A name for the profile. + /// Options for creating the profile. + /// True if the profile was created successfully, false otherwise. + /// + /// A V8 script engine can collect multiple CPU profiles simultaneously. + /// + public bool BeginCpuProfile(string name, V8CpuProfileFlags flags) + { + VerifyNotDisposed(); + return proxy.BeginCpuProfile(Name + ':' + name, flags); + } + + /// + /// Completes and returns a CPU profile. + /// + /// The name of the profile. + /// The profile if it was found and completed successfully, null otherwise. + /// + /// An empty argument selects the most recently created CPU profile. + /// + public V8CpuProfile EndCpuProfile(string name) + { + VerifyNotDisposed(); + return proxy.EndCpuProfile(Name + ':' + name); + } + + /// + /// Collects a sample in all CPU profiles active in the V8 runtime. + /// + public void CollectCpuProfileSample() + { + VerifyNotDisposed(); + proxy.CollectCpuProfileSample(); + } + + /// + /// Gets or sets the time interval between automatic CPU profile samples, in microseconds. + /// + /// + /// Assigning this property has no effect on CPU profiles already active in the V8 runtime. + /// The default value is 1000. + /// + public uint CpuProfileSampleInterval + { + get + { + VerifyNotDisposed(); + return proxy.CpuProfileSampleInterval; + } + + set + { + VerifyNotDisposed(); + proxy.CpuProfileSampleInterval = value; + } + } + + /// + /// Writes a snapshot of the V8 runtime's heap to the given stream. + /// + /// The stream to which to write the heap snapshot. + /// + /// This method generates a heap snapshot in JSON format with ASCII encoding. + /// + public void WriteRuntimeHeapSnapshot(Stream stream) + { + MiscHelpers.VerifyNonNullArgument(stream, nameof(stream)); + VerifyNotDisposed(); + + ScriptInvoke(() => proxy.WriteIsolateHeapSnapshot(stream)); + } + + #endregion + + #region internal members + + internal V8ContextProxy ContextProxy => proxy; + + internal V8Runtime.Statistics GetRuntimeStatistics() + { + VerifyNotDisposed(); + return proxy.GetIsolateStatistics(); + } + + internal Statistics GetStatistics() + { + VerifyNotDisposed(); + return ScriptInvoke(() => + { + var statistics = proxy.GetStatistics(); + + if (commonJSManager != null) + { + statistics.CommonJSModuleCacheSize = CommonJSManager.ModuleCacheSize; + } + + return statistics; + }); + } + + internal bool Equals(V8ScriptItem left, V8ScriptItem right) + { + if ((left.Engine is V8ScriptEngine leftEngine) && (right.Engine is V8ScriptEngine rightEngine) && (leftEngine.runtime == rightEngine.runtime) && (left.GetHashCode() == right.GetHashCode())) + { + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + return (bool)engineInternal.InvokeMethod("strictEquals", left, right); + } + + return false; + } + + internal CommonJSManager CommonJSManager => commonJSManager ?? (commonJSManager = new CommonJSManager(this)); + + internal JsonModuleManager JsonModuleManager => jsonDocumentManager ?? (jsonDocumentManager = new JsonModuleManager(this)); + + private object GetRootItem() + { + return MarshalToHost(ScriptInvoke(() => proxy.GetRootItem()), false); + } + + private void VerifyNotDisposed() + { + if (disposedFlag.IsSet) + { + throw new ObjectDisposedException(ToString()); + } + } + + // ReSharper disable ParameterHidesMember + + private object Execute(V8Script script, bool evaluate) + { + MiscHelpers.VerifyNonNullArgument(script, nameof(script)); + VerifyNotDisposed(); + + return MarshalToHost(ScriptInvoke(() => + { + if (inContinuationTimerScope || (ContinuationCallback == null)) + { + if (ShouldAwaitDebuggerAndPause(script.DocumentInfo)) + { + proxy.AwaitDebuggerAndPause(); + } + + return ExecuteInternal(script, evaluate); + } + + var state = new Timer[] { null }; + using (state[0] = new Timer(_ => OnContinuationTimer(state[0]), null, Timeout.Infinite, Timeout.Infinite)) + { + inContinuationTimerScope = true; + try + { + state[0].Change(continuationInterval, Timeout.Infinite); + + if (ShouldAwaitDebuggerAndPause(script.DocumentInfo)) + { + proxy.AwaitDebuggerAndPause(); + } + + return ExecuteInternal(script, evaluate); + } + finally + { + inContinuationTimerScope = false; + } + } + }), false); + } + + // ReSharper restore ParameterHidesMember + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + CommonJSManager.Module module = null; + if (documentInfo.Category == ModuleCategory.CommonJS) + { + module = CommonJSManager.GetOrCreateModule(documentInfo, code); + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot compile documents of type '" + documentInfo.Category + "'"); + } + + // ReSharper disable once LocalVariableHidesMember + var script = proxy.Compile(documentInfo, code); + + if (module != null) + { + module.Evaluator = () => proxy.Execute(script, true); + } + + return script; + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + CommonJSManager.Module module = null; + if (documentInfo.Category == ModuleCategory.CommonJS) + { + module = CommonJSManager.GetOrCreateModule(documentInfo, code); + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot compile documents of type '" + documentInfo.Category + "'"); + } + + // ReSharper disable once LocalVariableHidesMember + var script = proxy.Compile(documentInfo, code, cacheKind, out cacheBytes); + + if (module != null) + { + module.Evaluator = () => proxy.Execute(script, true); + } + + return script; + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + CommonJSManager.Module module = null; + if (documentInfo.Category == ModuleCategory.CommonJS) + { + module = CommonJSManager.GetOrCreateModule(documentInfo, code); + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot compile documents of type '" + documentInfo.Category + "'"); + } + + // ReSharper disable once LocalVariableHidesMember + var script = proxy.Compile(documentInfo, code, cacheKind, cacheBytes, out cacheAccepted); + + if (module != null) + { + module.Evaluator = () => proxy.Execute(script, true); + } + + return script; + } + + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + CommonJSManager.Module module = null; + if (documentInfo.Category == ModuleCategory.CommonJS) + { + module = CommonJSManager.GetOrCreateModule(documentInfo, code); + code = CommonJSManager.Module.GetAugmentedCode(code); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot compile documents of type '" + documentInfo.Category + "'"); + } + + // ReSharper disable once LocalVariableHidesMember + var script = proxy.Compile(documentInfo, code, cacheKind, ref cacheBytes, out cacheResult); + + if (module != null) + { + module.Evaluator = () => proxy.Execute(script, true); + } + + return script; + } + + private object ExecuteInternal(UniqueDocumentInfo documentInfo, string code, bool evaluate) + { + if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + } + + if (documentInfo.Category == ModuleCategory.CommonJS) + { + var module = CommonJSManager.GetOrCreateModule(documentInfo, code); + return module.Process(); + } + + if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot execute documents of type '" + documentInfo.Category + "'"); + } + + return ExecuteRaw(documentInfo, code, evaluate); + } + + // ReSharper disable ParameterHidesMember + + private object ExecuteInternal(V8Script script, bool evaluate) + { + if (script.UniqueDocumentInfo.Category == ModuleCategory.CommonJS) + { + var module = CommonJSManager.GetOrCreateModule(script.UniqueDocumentInfo, script.CodeDigest, () => proxy.Execute(script, evaluate)); + return module.Process(); + } + + return proxy.Execute(script, evaluate); + } + + // ReSharper restore ParameterHidesMember + + private bool ShouldAwaitDebuggerAndPause(DocumentInfo documentInfo) + { + if (!awaitDebuggerAndPause.HasValue) + { + if (documentInfo.Flags.GetValueOrDefault().HasFlag(DocumentFlags.AwaitDebuggerAndPause)) + { + awaitDebuggerAndPause = false; + return true; + } + + return false; + } + + if (awaitDebuggerAndPause.Value) + { + awaitDebuggerAndPause = false; + return true; + } + + return false; + } + + private void OnContinuationTimer(Timer timer) + { + try + { + var callback = ContinuationCallback; + if ((callback != null) && !callback()) + { + Interrupt(); + } + else + { + timer.Change(continuationInterval, Timeout.Infinite); + } + } + catch (ObjectDisposedException) + { + } + } + + private object CreatePromise(Action executor) + { + VerifyNotDisposed(); + var v8Internal = (V8ScriptItem)script.GetProperty("EngineInternal"); + return V8ScriptItem.Wrap(this, v8Internal.InvokeMethod(false, "createPromise", executor)); + } + + private void CompletePromise(Task task, object resolve, object reject) + { + Func getResult = () => task.Result; + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + engineInternal.InvokeMethod("completePromiseWithResult", getResult, resolve, reject); + } + + private void CompletePromise(Task task, object resolve, object reject) + { + Action wait = task.Wait; + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + engineInternal.InvokeMethod("completePromise", wait, resolve, reject); + } + + partial void TryConvertValueTaskToPromise(object obj, Action setResult); + + #endregion + + #region ScriptEngine overrides (public members) + + /// + /// Gets the script engine's recommended file name extension for script files. + /// + /// + /// instances return "js" for this property. + /// + public override string FileNameExtension => "js"; + + /// + public override dynamic Script + { + get + { + VerifyNotDisposed(); + return script; + } + } + + /// + public override ScriptObject Global + { + get + { + VerifyNotDisposed(); + return script; + } + } + + /// + /// Executes script code as a command. + /// + /// The script command to execute. + /// The command output. + /// + /// + /// This method is similar to but optimized for + /// command consoles. The specified command must be limited to a single expression or + /// statement. Script engines can override this method to customize command execution as + /// well as the process of converting the result to a string for console output. + /// + /// + /// The version of this method attempts to use + /// toString + /// to convert the return value. + /// + /// + public override string ExecuteCommand(string command) + { + return ScriptInvoke(() => + { + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + var commandHolder = (ScriptObject)engineInternal.GetProperty("commandHolder"); + commandHolder.SetProperty("command", command); + return base.ExecuteCommand("EngineInternal.getCommandResult(eval(EngineInternal.commandHolder.command))"); + }); + } + + /// + public override string GetStackTrace() + { + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + var stackTrace = (string)engineInternal.InvokeMethod("getStackTrace"); + var lines = stackTrace.Split('\n'); + return string.Join("\n", lines.Skip(2)); + } + + /// + /// Interrupts script execution and causes the script engine to throw an exception. + /// + /// + /// This method can be called safely from any thread. + /// + /// + public override void Interrupt() + { + VerifyNotDisposed(); + proxy.Interrupt(); + } + + /// + public override void CollectGarbage(bool exhaustive) + { + VerifyNotDisposed(); + proxy.CollectGarbage(exhaustive); + } + + #endregion + + #region ScriptEngine overrides (internal members) + + internal override IUniqueNameManager DocumentNameManager { get; } + + internal override bool EnumerateInstanceMethods => base.EnumerateInstanceMethods && !SuppressInstanceMethodEnumeration; + + internal override bool EnumerateExtensionMethods => base.EnumerateExtensionMethods && !SuppressExtensionMethodEnumeration; + + internal override bool UseCaseInsensitiveMemberBinding => engineFlags.HasFlag(V8ScriptEngineFlags.UseCaseInsensitiveMemberBinding); + + internal override void AddHostItem(string itemName, HostItemFlags flags, object item) + { + VerifyNotDisposed(); + + var globalMembers = flags.HasFlag(HostItemFlags.GlobalMembers); + if (globalMembers && engineFlags.HasFlag(V8ScriptEngineFlags.DisableGlobalMembers)) + { + throw new InvalidOperationException("GlobalMembers support is disabled in this script engine"); + } + + MiscHelpers.VerifyNonNullArgument(itemName, nameof(itemName)); + Debug.Assert(item != null); + + ScriptInvoke(() => + { + object marshaledItem; + +#if NETCOREAPP || NETSTANDARD + if (item is SplitProxy.IV8HostObject || item is SplitProxy.InvokeHostObject) + { + marshaledItem = item; + } + else +#endif + { + marshaledItem = MarshalToScript(item, flags); + if (!(marshaledItem is HostItem)) + { + throw new InvalidOperationException("Invalid host item"); + } + } + + proxy.AddGlobalItem(itemName, marshaledItem, globalMembers); + }); + } + + internal override object MarshalToScript(object obj, HostItemFlags flags) + { + const long maxIntInDouble = (1L << 53) - 1; + + if (obj == null) + { + obj = NullExportValue; + } + + if (obj == null) + { + return DBNull.Value; + } + + if (obj is DBNull) + { + return obj; + } + + if (obj is Undefined) + { + return null; + } + + if (obj is Nonexistent) + { + return obj; + } + + if (obj is INothingTag) + { + return null; + } + + if (obj is BigInteger) + { + return obj; + } + + if (obj is long longValue) + { + if (engineFlags.HasFlag(V8ScriptEngineFlags.MarshalAllLongAsBigInt)) + { + return new BigInteger(longValue); + } + + if (engineFlags.HasFlag(V8ScriptEngineFlags.MarshalUnsafeLongAsBigInt) && (Math.Abs(longValue) > maxIntInDouble)) + { + return new BigInteger(longValue); + } + } + + if (obj is ulong ulongValue) + { + if (engineFlags.HasFlag(V8ScriptEngineFlags.MarshalAllLongAsBigInt)) + { + return new BigInteger(ulongValue); + } + + if (engineFlags.HasFlag(V8ScriptEngineFlags.MarshalUnsafeLongAsBigInt) && (ulongValue > maxIntInDouble)) + { + return new BigInteger(ulongValue); + } + } + + if (engineFlags.HasFlag(V8ScriptEngineFlags.EnableDateTimeConversion) && (obj is DateTime)) + { + return obj; + } + + if (engineFlags.HasFlag(V8ScriptEngineFlags.EnableTaskPromiseConversion)) + { + // .NET Core async functions return Task subclass instances that trigger result wrapping + + var testObject = obj; + if (testObject is HostObject testHostObject) + { + testObject = testHostObject.Target; + } + + if (testObject != null) + { + if (testObject.GetType().IsAssignableToGenericType(typeof(Task<>), out var typeArgs)) + { + obj = typeof(TaskConverter<>).MakeSpecificType(typeArgs).InvokeMember("ToPromise", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new[] { testObject, this }); + } + else if (testObject is Task task) + { + obj = task.ToPromise(this); + } + else if (engineFlags.HasFlag(V8ScriptEngineFlags.EnableValueTaskPromiseConversion)) + { + TryConvertValueTaskToPromise(testObject, result => obj = result); + } + } + } + + if (obj is HostItem hostItem) + { + if ((hostItem.Engine == this) && (hostItem.Flags == flags)) + { + return obj; + } + + obj = hostItem.Target; + } + + var hostTarget = obj as HostTarget; + if ((hostTarget != null) && !(hostTarget is IHostVariable)) + { + obj = hostTarget.Target; + } + + if (obj is ScriptItem scriptItem) + { + if ((scriptItem.Engine is V8ScriptEngine that) && (that.runtime == runtime)) + { + return scriptItem.Unwrap(); + } + + if ((scriptItem is V8ScriptItem v8ScriptItem) && v8ScriptItem.IsShared) + { + return scriptItem.Unwrap(); + } + } + + return HostItem.Wrap(this, hostTarget ?? obj, flags); + } + + internal override object MarshalToHost(object obj, bool preserveHostTarget) + { + if (obj == null) + { + return UndefinedImportValue; + } + + if (obj is DBNull) + { + return null; + } + + if (MiscHelpers.TryMarshalPrimitiveToHost(obj, DisableFloatNarrowing, out var result)) + { + return result; + } + + if (obj is HostTarget hostTarget) + { + return preserveHostTarget ? hostTarget : hostTarget.Target; + } + + if (obj is HostItem hostItem) + { + return preserveHostTarget ? hostItem.Target : hostItem.Unwrap(); + } + + if (obj is ScriptItem) + { + return obj; + } + + var scriptItem = V8ScriptItem.Wrap(this, obj); + if (engineFlags.HasFlag(V8ScriptEngineFlags.EnableTaskPromiseConversion) && (obj is IV8Object v8Object) && v8Object.IsPromise) + { + return scriptItem.ToTask(); + } + + return scriptItem; + } + + internal override object Execute(UniqueDocumentInfo documentInfo, string code, bool evaluate) + { + VerifyNotDisposed(); + + return ScriptInvoke(() => + { + if ((documentNames != null) && !documentInfo.Flags.GetValueOrDefault().HasFlag(DocumentFlags.IsTransient)) + { + documentNames.Add(documentInfo.UniqueName); + } + + if (inContinuationTimerScope || (ContinuationCallback == null)) + { + if (ShouldAwaitDebuggerAndPause(documentInfo.Info)) + { + proxy.AwaitDebuggerAndPause(); + } + + return ExecuteInternal(documentInfo, code, evaluate); + } + + var state = new Timer[] { null }; + using (state[0] = new Timer(_ => OnContinuationTimer(state[0]), null, Timeout.Infinite, Timeout.Infinite)) + { + inContinuationTimerScope = true; + try + { + state[0].Change(continuationInterval, Timeout.Infinite); + + if (ShouldAwaitDebuggerAndPause(documentInfo.Info)) + { + proxy.AwaitDebuggerAndPause(); + } + + return ExecuteInternal(documentInfo, code, evaluate); + } + finally + { + inContinuationTimerScope = false; + } + } + }); + } + + internal override object ExecuteRaw(UniqueDocumentInfo documentInfo, string code, bool evaluate) + { + return proxy.Execute(documentInfo, code, evaluate); + } + + internal override HostItemCollateral HostItemCollateral { get; } + + internal override void OnAccessSettingsChanged() + { + base.OnAccessSettingsChanged(); + ScriptInvoke(() => proxy.OnAccessSettingsChanged()); + } + + #endregion + + #region ScriptEngine overrides (script-side invocation) + + internal override void ScriptInvoke(Action action) + { + VerifyNotDisposed(); + using (CreateEngineScope()) + { + proxy.InvokeWithLock(() => ScriptInvokeInternal(action)); + } + } + + internal override T ScriptInvoke(Func func) + { + VerifyNotDisposed(); + using (CreateEngineScope()) + { + var result = default(T); + proxy.InvokeWithLock(() => result = ScriptInvokeInternal(func)); + return result; + } + } + + #endregion + + #region ScriptEngine overrides (disposal / finalization) + + /// + /// Releases the unmanaged resources used by the script engine and optionally releases the managed resources. + /// + /// True to release both managed and unmanaged resources; false to release only unmanaged resources. + /// + /// This method is called by the public method and the + /// Finalize method. + /// invokes the protected Dispose(Boolean) + /// method with the parameter set to true. + /// Finalize invokes Dispose(Boolean) with + /// set to false. + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (disposedFlag.Set()) + { + base.Dispose(true); + + ((IDisposable)script).Dispose(); + proxy.Dispose(); + + if (usingPrivateRuntime) + { + runtime.Dispose(); + } + } + } + else + { + base.Dispose(false); + } + } + + #endregion + + #region IJavaScriptEngine implementation + + uint IJavaScriptEngine.BaseLanguageVersion => 8; + + CommonJSManager IJavaScriptEngine.CommonJSManager => CommonJSManager; + + JsonModuleManager IJavaScriptEngine.JsonModuleManager => JsonModuleManager; + + object IJavaScriptEngine.CreatePromiseForTask(Task task) + { + var scheduler = (engineFlags.HasFlag(V8ScriptEngineFlags.UseSynchronizationContexts) && MiscHelpers.Try(out var contextScheduler, TaskScheduler.FromCurrentSynchronizationContext)) ? contextScheduler : TaskScheduler.Current; + return CreatePromise((resolve, reject) => + { + task.ContinueWith(_ => CompletePromise(task, resolve, reject), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler); + }); + } + + object IJavaScriptEngine.CreatePromiseForTask(Task task) + { + var scheduler = (engineFlags.HasFlag(V8ScriptEngineFlags.UseSynchronizationContexts) && MiscHelpers.Try(out var contextScheduler, TaskScheduler.FromCurrentSynchronizationContext)) ? contextScheduler : TaskScheduler.Current; + return CreatePromise((resolve, reject) => + { + task.ContinueWith(_ => CompletePromise(task, resolve, reject), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler); + }); + } + + Task IJavaScriptEngine.CreateTaskForPromise(ScriptObject promise) + { + if (!(promise is V8ScriptItem v8ScriptItem) || !v8ScriptItem.IsPromise) + { + throw new ArgumentException("The object is not a V8 promise", nameof(promise)); + } + + var source = new TaskCompletionSource(); + var context = engineFlags.HasFlag(V8ScriptEngineFlags.UseSynchronizationContexts) ? SynchronizationContext.Current : null; + + Action setResultWorker = result => source.SetResult(result); + var setResult = (context == null) ? setResultWorker : result => context.Post(_ => setResultWorker(result), null); + + Action setExceptionWorker = exception => source.SetException(exception); + var setException = (context == null) ? setExceptionWorker : exception => context.Post(_ => setExceptionWorker(exception), null); + + Action onResolved = result => + { + setResult(result); + }; + + Action onRejected = error => + { + try + { + var engineInternal = (ScriptObject)script.GetProperty("EngineInternal"); + engineInternal.InvokeMethod("throwValue", error); + } + catch (Exception exception) + { + setException(exception); + } + }; + + v8ScriptItem.InvokeMethod(false, "then", onResolved, onRejected); + + return source.Task; + } + + #endregion + + #region unit test support + + internal void EnableDocumentNameTracking() + { + documentNames = new List(); + } + + internal IEnumerable GetDocumentNames() + { + return documentNames; + } + + #endregion + + #region Nested type: Statistics + + internal sealed class Statistics + { + public ulong ScriptCount; + public ulong ModuleCount; + public ulong ModuleCacheSize; + public int CommonJSModuleCacheSize; + } + + #endregion + + #region Nested type: TaskConverter + + private static class TaskConverter + { + // ReSharper disable UnusedMember.Local + + public static object ToPromise(Task task, V8ScriptEngine engine) + { + return task.ToPromise(engine); + } + + // ReSharper restore UnusedMember.Local + } + + #endregion + + #region Nested type: JsonHelper + + /// + public sealed class JsonHelper : JsonConverter + { + private readonly ScriptObject stringify; + private readonly HashSet cycleDetectionSet = new HashSet(); + + /// + public JsonHelper(V8ScriptEngine engine) + { + var json = (ScriptObject)engine.script.GetProperty("JSON"); + stringify = (ScriptObject)json.GetProperty("stringify"); + } + + /// + public string ToJson(object key, object value) + { + key = MiscHelpers.EnsureNonBlank(key.ToString(), "[root]"); + + if (cycleDetectionSet.Contains(value)) + { + throw new InvalidOperationException($"Cycle detected at key '{key}' during JSON serialization"); + } + + cycleDetectionSet.Add(value); + try + { + return JsonConvert.SerializeObject(value, this); + } + finally + { + cycleDetectionSet.Remove(value); + } + } + + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var result = stringify.Invoke(false, value); + writer.WriteRawValue(result as string ?? "null"); + } + + /// + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => throw new NotImplementedException(); + + /// + public override bool CanConvert(Type objectType) => typeof(V8ScriptItem).IsAssignableFrom(objectType); + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8ScriptEngine.cs.meta b/Unity/Package/Runtime/V8/V8ScriptEngine.cs.meta new file mode 100644 index 000000000..6d0f9b9c2 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b031f28cb658c4341bbe5c00d5e215bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs b/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs new file mode 100644 index 000000000..9fb36b3f5 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines options for initializing a new V8 JavaScript engine instance. + /// + [Flags] + public enum V8ScriptEngineFlags + { + // IMPORTANT: maintain bitwise equivalence with unmanaged enum V8Context::Flags + + /// + /// Specifies that no options are selected. + /// + None = 0, + + /// + /// Specifies that script debugging features are to be enabled. + /// + EnableDebugging = 0x00000001, + + /// + /// Specifies that support for behavior is to be + /// disabled. This option yields a significant performance benefit for global item access. + /// + DisableGlobalMembers = 0x00000002, + + /// + /// Specifies that remote script debugging is to be enabled. This option is ignored if + /// is not specified. + /// + EnableRemoteDebugging = 0x00000004, + + /// + /// Specifies that the script engine is to wait for a debugger connection and schedule a + /// pause before executing the first line of application script code. This option is + /// ignored if is not specified. + /// + AwaitDebuggerAndPauseOnStart = 0x00000008, + + /// + /// Specifies that the script engine is to perform automatic conversion between + /// .NET objects and JavaScript + /// Date + /// objects. This conversion is bidirectional and lossy. A DateTime object + /// constructed from a JavaScript Date object always represents a Coordinated + /// Universal Time (UTC) and has its property set to + /// . + /// + EnableDateTimeConversion = 0x00000010, + + /// + /// Specifies that + /// dynamic module imports + /// are to be enabled. This is an experimental feature and may be removed in a future release. + /// + EnableDynamicModuleImports = 0x00000020, + + /// + /// Specifies that long integers with values greater than + /// Number.MAX_SAFE_INTEGER + /// or less than + /// Number.MIN_SAFE_INTEGER + /// are to be marshaled as + /// BigInt. + /// This option is ignored if is specified. + /// + MarshalUnsafeLongAsBigInt = 0x00000040, + + /// + /// Specifies that all long integers are to be marshaled as + /// BigInt. + /// + MarshalAllLongAsBigInt = 0x00000080, + + /// + /// Specifies that the script engine is to perform automatic conversion between + /// .NET objects and JavaScript + /// promises. + /// This conversion is bidirectional and lossy. A Task object constructed from a + /// JavaScript promise always has a result type of . + /// + EnableTaskPromiseConversion = 0x00000100, + + /// + /// Specifies that the script engine is to perform automatic conversion from + /// .NET + /// ValueTask and + /// ValueTask<TResult> + /// structures to JavaScript + /// promises. + /// This conversion is unidirectional and lossy. This option is ignored if + /// is not specified. + /// + EnableValueTaskPromiseConversion = 0x00000200, + + /// + /// Specifies that access to host object and class members is to be case-insensitive. This + /// option can introduce ambiguity if the host resource has distinct members whose names + /// differ only in case, so it should be used with caution. + /// + UseCaseInsensitiveMemberBinding = 0x00000400, + + /// + /// Specifies that + /// JSON.stringify + /// enhancements are to be enabled. These enhancements add support for host objects via the + /// Json.NET library. + /// + EnableStringifyEnhancements = 0x00000800, + + /// + /// Specifies that host exceptions are to be hidden from script code. If an exception + /// thrown by the host reaches the script engine, it is caught automatically, and an + /// Error + /// object is thrown in its place. By default, ClearScript makes the managed exception + /// accessible to script code via the Error object's hostException property. + /// This option suppresses that behavior. + /// + HideHostExceptions = 0x00001000, + + /// + /// Specifies that support for synchronization contexts is to be enabled for task-promise + /// interoperability. This option is ignored if + /// is not specified. + /// + UseSynchronizationContexts = 0x00002000, + + /// + /// Specifies that the + /// Performance + /// object is to be added to the script engine's global namespace. This object provides a + /// set of low-level native facilities for performance-sensitive scripts. + /// + AddPerformanceObject = 0x00004000, + + /// + /// Specifies that native timers are to be set to the highest available resolution while + /// the current instance is active. This option is + /// ignored if is not specified. It is only a + /// hint and may be ignored on some systems. On platforms that support it, this option can + /// degrade overall system performance or power efficiency, so caution is recommended. + /// + SetTimerResolution = 0x00008000 + } +} diff --git a/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs.meta b/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs.meta new file mode 100644 index 000000000..b75cf21bf --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptEngineFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22e36b7c3d3444748a39c1cfe7ffc322 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8ScriptItem.cs b/Unity/Package/Runtime/V8/V8ScriptItem.cs new file mode 100644 index 000000000..49eeba8bb --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptItem.cs @@ -0,0 +1,973 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Linq; +using Microsoft.ClearScript.JavaScript; +using Microsoft.ClearScript.Util; +using Microsoft.ClearScript.Util.COM; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract class V8ScriptItem : ScriptItem, IJavaScriptObject + { + private readonly V8ScriptEngine engine; + private readonly IV8Object target; + private V8ScriptItem holder; + private readonly InterlockedOneWayFlag disposedFlag = new InterlockedOneWayFlag(); + + private V8ScriptItem(V8ScriptEngine engine, IV8Object target) + { + this.engine = engine; + this.target = target; + } + + public static object Wrap(V8ScriptEngine engine, object obj) + { + Debug.Assert(!(obj is IScriptMarshalWrapper)); + + if (obj == null) + { + return null; + } + + if (obj is IV8Object target) + { + if (target.IsArray) + { + return new V8Array(engine, target); + } + + if (!target.IsArrayBufferOrView) + { + return new V8ScriptObject(engine, target); + } + + switch (target.ArrayBufferOrViewKind) + { + case V8ArrayBufferOrViewKind.ArrayBuffer: + return new V8ArrayBuffer(engine, target); + + case V8ArrayBufferOrViewKind.DataView: + return new V8DataView(engine, target); + + case V8ArrayBufferOrViewKind.Uint8Array: + case V8ArrayBufferOrViewKind.Uint8ClampedArray: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Int8Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Uint16Array: + return new V8UInt16Array(engine, target); + + case V8ArrayBufferOrViewKind.Int16Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Uint32Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Int32Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.BigUint64Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.BigInt64Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Float32Array: + return new V8TypedArray(engine, target); + + case V8ArrayBufferOrViewKind.Float64Array: + return new V8TypedArray(engine, target); + + default: + return new V8ScriptObject(engine, target); + } + } + + return obj; + } + + public bool IsPromise => target.IsPromise; + + public bool IsShared => target.IsShared; + + public object InvokeMethod(bool marshalResult, string name, params object[] args) + { + VerifyNotDisposed(); + + var result = engine.ScriptInvoke(() => target.InvokeMethod(name, engine.MarshalToScript(args))); + if (marshalResult) + { + return engine.MarshalToHost(result, false); + } + + return result; + } + + private void VerifyNotDisposed() + { + if (disposedFlag.IsSet) + { + throw new ObjectDisposedException(ToString()); + } + } + + #region ScriptItem overrides + + protected override bool TryBindAndInvoke(DynamicMetaObjectBinder binder, object[] args, out object result) + { + VerifyNotDisposed(); + + try + { + if (binder is GetMemberBinder getMemberBinder) + { + result = target.GetProperty(getMemberBinder.Name); + return true; + } + + if ((binder is SetMemberBinder setMemberBinder) && (args != null) && (args.Length > 0)) + { + target.SetProperty(setMemberBinder.Name, args[0]); + result = args[0]; + return true; + } + + if (binder is GetIndexBinder) + { + if ((args != null) && (args.Length == 1)) + { + result = MiscHelpers.TryGetNumericIndex(args[0], out int index) ? target.GetProperty(index) : target.GetProperty(args[0].ToString()); + return true; + } + + throw new InvalidOperationException("Invalid argument or index count"); + } + + if (binder is SetIndexBinder) + { + if ((args != null) && (args.Length == 2)) + { + if (MiscHelpers.TryGetNumericIndex(args[0], out int index)) + { + target.SetProperty(index, args[1]); + } + else + { + target.SetProperty(args[0].ToString(), args[1]); + } + + result = args[1]; + return true; + } + + throw new InvalidOperationException("Invalid argument or index count"); + } + + if (binder is InvokeBinder) + { + result = target.Invoke(false, args); + return true; + } + + if (binder is InvokeMemberBinder invokeMemberBinder) + { + result = target.InvokeMethod(invokeMemberBinder.Name, args); + return true; + } + } + catch (Exception exception) + { + if (engine.CurrentScriptFrame != null) + { + if (exception is IScriptEngineException scriptError) + { + if (scriptError.ExecutionStarted) + { + throw; + } + + engine.CurrentScriptFrame.ScriptError = scriptError; + } + else + { + engine.CurrentScriptFrame.ScriptError = new ScriptEngineException(engine.Name, exception.Message, null, HResult.CLEARSCRIPT_E_SCRIPTITEMEXCEPTION, false, false, null, exception); + } + } + } + + result = null; + return false; + } + + public override string[] GetPropertyNames() + { + VerifyNotDisposed(); + return engine.ScriptInvoke(() => target.GetPropertyNames(false /*includeIndices*/)); + } + + public override int[] GetPropertyIndices() + { + VerifyNotDisposed(); + return engine.ScriptInvoke(() => target.GetPropertyIndices()); + } + + #endregion + + #region ScriptObject overrides + + public override object GetProperty(string name, params object[] args) + { + VerifyNotDisposed(); + if ((args != null) && (args.Length != 0)) + { + throw new InvalidOperationException("Invalid argument or index count"); + } + + var result = engine.MarshalToHost(engine.ScriptInvoke(() => target.GetProperty(name)), false); + + if ((result is V8ScriptItem resultScriptItem) && (resultScriptItem.engine == engine)) + { + resultScriptItem.holder = this; + } + + return result; + } + + public override void SetProperty(string name, params object[] args) + { + VerifyNotDisposed(); + if ((args == null) || (args.Length != 1)) + { + throw new InvalidOperationException("Invalid argument or index count"); + } + + engine.ScriptInvoke(() => target.SetProperty(name, engine.MarshalToScript(args[0]))); + } + + public override bool DeleteProperty(string name) + { + VerifyNotDisposed(); + return engine.ScriptInvoke(() => target.DeleteProperty(name)); + } + + public override object GetProperty(int index) + { + VerifyNotDisposed(); + return engine.MarshalToHost(engine.ScriptInvoke(() => target.GetProperty(index)), false); + } + + public override void SetProperty(int index, object value) + { + VerifyNotDisposed(); + engine.ScriptInvoke(() => target.SetProperty(index, engine.MarshalToScript(value))); + } + + public override bool DeleteProperty(int index) + { + VerifyNotDisposed(); + return engine.ScriptInvoke(() => target.DeleteProperty(index)); + } + + public override object Invoke(bool asConstructor, params object[] args) + { + VerifyNotDisposed(); + + if (asConstructor || (holder == null)) + { + return engine.MarshalToHost(engine.ScriptInvoke(() => target.Invoke(asConstructor, engine.MarshalToScript(args))), false); + } + + var engineInternal = (ScriptObject)engine.Global.GetProperty("EngineInternal"); + return engineInternal.InvokeMethod("invokeMethod", holder, this, args); + } + + public override object InvokeMethod(string name, params object[] args) + { + return InvokeMethod(true, name, args); + } + + #endregion + + #region IScriptMarshalWrapper implementation + + public override ScriptEngine Engine => engine; + + public override object Unwrap() + { + return target; + } + + #endregion + + #region Object overrides + + public override bool Equals(object obj) => (obj is V8ScriptItem that) && engine.Equals(this, that); + + public override int GetHashCode() => target.IdentityHash; + + #endregion + + #region IJavaScriptObject implementation + + public JavaScriptObjectKind Kind => target.ObjectKind; + + public JavaScriptObjectFlags Flags => target.ObjectFlags; + + #endregion + + #region IDisposable implementation + + public override void Dispose() + { + if (disposedFlag.Set()) + { + target.Dispose(); + } + } + + #endregion + + #region Nested type: V8ScriptObject + + private sealed class V8ScriptObject : V8ScriptItem, IDictionary + { + public V8ScriptObject(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + private bool TryGetProperty(string name, out object value) + { + VerifyNotDisposed(); + + object tempResult = null; + if (engine.ScriptInvoke(() => target.TryGetProperty(name, out tempResult))) + { + var result = engine.MarshalToHost(tempResult, false); + if ((result is V8ScriptItem resultScriptItem) && (resultScriptItem.engine == engine)) + { + resultScriptItem.holder = this; + } + + value = result; + return true; + } + + value = null; + return false; + } + + #region IDictionary implementation + + private IDictionary ThisDictionary => this; + + private IEnumerable PropertyKeys => GetPropertyKeys(); + + private IEnumerable> KeyValuePairs => PropertyKeys.Select(name => new KeyValuePair(name, GetProperty(name))); + + private string[] GetPropertyKeys() + { + VerifyNotDisposed(); + return engine.ScriptInvoke(() => target.GetPropertyNames(true /*includeIndices*/)); + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + return KeyValuePairs.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ThisDictionary.GetEnumerator(); + } + + void ICollection>.Add(KeyValuePair item) + { + SetProperty(item.Key, item.Value); + } + + void ICollection>.Clear() + { + PropertyKeys.ForEach(name => DeleteProperty(name)); + } + + bool ICollection>.Contains(KeyValuePair item) + { + return TryGetProperty(item.Key, out var value) && Equals(value, item.Value); + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + var source = KeyValuePairs.ToArray(); + Array.Copy(source, 0, array, arrayIndex, source.Length); + } + + bool ICollection>.Remove(KeyValuePair item) + { + return ThisDictionary.Contains(item) && DeleteProperty(item.Key); + } + + int ICollection>.Count => PropertyKeys.Count(); + + bool ICollection>.IsReadOnly => false; + + void IDictionary.Add(string key, object value) + { + SetProperty(key, value); + } + + bool IDictionary.ContainsKey(string key) + { + return PropertyKeys.Contains(key); + } + + bool IDictionary.Remove(string key) + { + return DeleteProperty(key); + } + + bool IDictionary.TryGetValue(string key, out object value) + { + return TryGetProperty(key, out value); + } + + object IDictionary.this[string key] + { + get => TryGetProperty(key, out var value) ? value : throw new KeyNotFoundException(); + set => SetProperty(key, value); + } + + ICollection IDictionary.Keys => PropertyKeys.ToList(); + + ICollection IDictionary.Values => PropertyKeys.Select(name => GetProperty(name)).ToList(); + + #endregion + } + + #endregion + + #region Nested type: V8Array + + private sealed class V8Array : V8ScriptItem, IList, IList + { + public V8Array(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + #region IList implementation + + private IList ThisGenericList => this; + + IEnumerator IEnumerable.GetEnumerator() + { + return new Enumerator(this); + } + + bool ICollection.Remove(object item) + { + var index = ThisList.IndexOf(item); + if (index >= 0) + { + ThisList.RemoveAt(index); + return true; + } + + return false; + } + + int ICollection.Count => ThisList.Count; + + bool ICollection.IsReadOnly => ThisList.IsReadOnly; + + void ICollection.Clear() + { + ThisList.Clear(); + } + + bool ICollection.Contains(object item) + { + return ThisList.Contains(item); + } + + void ICollection.CopyTo(object[] array, int arrayIndex) + { + ThisList.CopyTo(array, arrayIndex); + } + + void ICollection.Add(object item) + { + ThisList.Add(item); + } + + void IList.Insert(int index, object item) + { + ThisList.Insert(index, item); + } + + void IList.RemoveAt(int index) + { + ThisList.RemoveAt(index); + } + + int IList.IndexOf(object item) + { + return ThisList.IndexOf(item); + } + + #endregion + + #region IList implementation + + private IList ThisList => this; + + IEnumerator IEnumerable.GetEnumerator() + { + return ThisGenericList.GetEnumerator(); + } + + void ICollection.CopyTo(Array array, int index) + { + MiscHelpers.VerifyNonNullArgument(array, nameof(array)); + + if (array.Rank > 1) + { + throw new ArgumentException("Invalid target array", nameof(array)); + } + + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + var length = ThisList.Count; + if ((index + length) > array.Length) + { + throw new ArgumentException("Insufficient space in target array", nameof(array)); + } + + for (var sourceIndex = 0; sourceIndex < length; sourceIndex++) + { + array.SetValue(this[sourceIndex], index + sourceIndex); + } + } + + int ICollection.Count => Convert.ToInt32(GetProperty("length")); + + object ICollection.SyncRoot => this; + + bool ICollection.IsSynchronized => false; + + int IList.Add(object value) + { + return Convert.ToInt32(InvokeMethod("push", value)) - 1; + } + + bool IList.Contains(object value) + { + return ThisList.IndexOf(value) >= 0; + } + + void IList.Clear() + { + InvokeMethod("splice", 0, ThisList.Count); + } + + int IList.IndexOf(object value) + { + return Convert.ToInt32(InvokeMethod("indexOf", value)); + } + + void IList.Insert(int index, object value) + { + InvokeMethod("splice", index, 0, value); + } + + void IList.Remove(object value) + { + ThisGenericList.Remove(value); + } + + void IList.RemoveAt(int index) + { + InvokeMethod("splice", index, 1); + } + + bool IList.IsReadOnly => false; + + bool IList.IsFixedSize => false; + + #region Nested type: Enumerator + + private class Enumerator : IEnumerator + { + private readonly V8Array array; + private readonly int count; + private int index = -1; + + public Enumerator(V8Array array) + { + this.array = array; + count = array.ThisList.Count; + } + + public bool MoveNext() + { + if (index >= (count - 1)) + { + return false; + } + + ++index; + return true; + } + + public void Reset() + { + index = -1; + } + + public object Current => array[index]; + + public void Dispose() + { + } + } + + #endregion + + #endregion + } + + #endregion + + #region Nested type: V8ArrayBufferOrView + + private abstract class V8ArrayBufferOrView : V8ScriptItem + { + private V8ArrayBufferOrViewInfo info; + private IArrayBuffer arrayBuffer; + + protected V8ArrayBufferOrView(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + protected IArrayBuffer ArrayBuffer => GetArrayBuffer(); + + protected ulong Offset => GetInfo().Offset; + + protected ulong Size => GetInfo().Size; + + protected ulong Length => GetInfo().Length; + + protected byte[] GetBytes() + { + var size = Size; + var result = new byte[size]; + InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(pData, size, result, 0)); + return result; + } + + protected ulong ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex) + { + var size = Size; + if (offset >= size) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(GetPtrWithOffset(pData, offset), Math.Min(count, size - offset), destination, destinationIndex)); + } + + protected ulong WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset) + { + var size = Size; + if (offset >= size) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(source, sourceIndex, Math.Min(count, size - offset), GetPtrWithOffset(pData, offset))); + } + + protected void InvokeWithDirectAccess(Action action) + { + engine.ScriptInvoke(() => target.InvokeWithArrayBufferOrViewData(action)); + } + + protected T InvokeWithDirectAccess(Func func) + { + return engine.ScriptInvoke(() => + { + var result = default(T); + target.InvokeWithArrayBufferOrViewData(pData => result = func(pData)); + return result; + }); + } + + private V8ArrayBufferOrViewInfo GetInfo() + { + VerifyNotDisposed(); + + if (info == null) + { + engine.ScriptInvoke(() => + { + if (info == null) + { + info = target.GetArrayBufferOrViewInfo(); + } + }); + } + + return info; + } + + private IArrayBuffer GetArrayBuffer() + { + return arrayBuffer ?? (arrayBuffer = (IArrayBuffer)engine.MarshalToHost(GetInfo().ArrayBuffer, false)); + } + + private static IntPtr GetPtrWithOffset(IntPtr pData, ulong offset) + { + var baseAddr = unchecked((ulong)pData.ToInt64()); + return new IntPtr(unchecked((long)checked(baseAddr + offset))); + } + } + + #endregion + + #region Nested type: V8ArrayBuffer + + private sealed class V8ArrayBuffer : V8ArrayBufferOrView, IArrayBuffer + { + public V8ArrayBuffer(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + #region IArrayBuffer implementation + + ulong IArrayBuffer.Size => Size; + + byte[] IArrayBuffer.GetBytes() + { + return GetBytes(); + } + + ulong IArrayBuffer.ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex) + { + return ReadBytes(offset, count, destination, destinationIndex); + } + + ulong IArrayBuffer.WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset) + { + return WriteBytes(source, sourceIndex, count, offset); + } + + void IArrayBuffer.InvokeWithDirectAccess(Action action) + { + MiscHelpers.VerifyNonNullArgument(action, nameof(action)); + InvokeWithDirectAccess(action); + } + + T IArrayBuffer.InvokeWithDirectAccess(Func func) + { + MiscHelpers.VerifyNonNullArgument(func, nameof(func)); + return InvokeWithDirectAccess(func); + } + + #endregion + } + + #endregion + + #region Nested type: V8ArrayBufferView + + private abstract class V8ArrayBufferView : V8ArrayBufferOrView, IArrayBufferView + { + protected V8ArrayBufferView(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + #region IArrayBufferView implementation + + IArrayBuffer IArrayBufferView.ArrayBuffer => ArrayBuffer; + + ulong IArrayBufferView.Offset => Offset; + + ulong IArrayBufferView.Size => Size; + + byte[] IArrayBufferView.GetBytes() + { + return GetBytes(); + } + + ulong IArrayBufferView.ReadBytes(ulong offset, ulong count, byte[] destination, ulong destinationIndex) + { + return ReadBytes(offset, count, destination, destinationIndex); + } + + ulong IArrayBufferView.WriteBytes(byte[] source, ulong sourceIndex, ulong count, ulong offset) + { + return WriteBytes(source, sourceIndex, count, offset); + } + + void IArrayBufferView.InvokeWithDirectAccess(Action action) + { + MiscHelpers.VerifyNonNullArgument(action, nameof(action)); + InvokeWithDirectAccess(action); + } + + T IArrayBufferView.InvokeWithDirectAccess(Func func) + { + MiscHelpers.VerifyNonNullArgument(func, nameof(func)); + return InvokeWithDirectAccess(func); + } + + #endregion + } + + #endregion + + #region Nested type: V8DataView + + private sealed class V8DataView : V8ArrayBufferView, IDataView + { + public V8DataView(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + } + + #endregion + + #region Nested type: V8TypedArray + + private class V8TypedArray : V8ArrayBufferView, ITypedArray + { + protected V8TypedArray(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + protected IntPtr GetPtrWithIndex(IntPtr pData, ulong index) + { + var baseAddr = unchecked((ulong)pData.ToInt64()); + return new IntPtr(unchecked((long)checked(baseAddr + (index * (Size / Length))))); + } + + #region ITypedArray implementation + + ulong ITypedArray.Length => Length; + + #endregion + } + + #endregion + + #region Nested type: V8TypedArray + + private class V8TypedArray : V8TypedArray, ITypedArray + { + public V8TypedArray(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + #region ITypedArray implementation + + T[] ITypedArray.ToArray() + { + var length = Length; + var result = new T[length]; + InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(pData, length, result, 0)); + return result; + } + + ulong ITypedArray.Read(ulong index, ulong length, T[] destination, ulong destinationIndex) + { + var totalLength = Length; + if (index >= totalLength) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(GetPtrWithIndex(pData, index), Math.Min(length, totalLength - index), destination, destinationIndex)); + } + + ulong ITypedArray.Write(T[] source, ulong sourceIndex, ulong length, ulong index) + { + var totalLength = Length; + if (index >= totalLength) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(source, sourceIndex, Math.Min(length, totalLength - index), GetPtrWithIndex(pData, index))); + } + + #endregion + } + + #endregion + + #region Nested type: V8UInt16Array + + // special case to support both ITypedArray and ITypedArray + + private sealed class V8UInt16Array : V8TypedArray, ITypedArray + { + public V8UInt16Array(V8ScriptEngine engine, IV8Object target) + : base(engine, target) + { + } + + #region ITypedArray implementation + + char[] ITypedArray.ToArray() + { + var length = Length; + var result = new char[length]; + InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(pData, length, result, 0)); + return result; + } + + ulong ITypedArray.Read(ulong index, ulong length, char[] destination, ulong destinationIndex) + { + var totalLength = Length; + if (index >= totalLength) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(GetPtrWithIndex(pData, index), Math.Min(length, totalLength - index), destination, destinationIndex)); + } + + ulong ITypedArray.Write(char[] source, ulong sourceIndex, ulong length, ulong index) + { + var totalLength = Length; + if (index >= totalLength) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return InvokeWithDirectAccess(pData => UnmanagedMemoryHelpers.Copy(source, sourceIndex, Math.Min(length, totalLength - index), GetPtrWithIndex(pData, index))); + } + + #endregion + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8ScriptItem.cs.meta b/Unity/Package/Runtime/V8/V8ScriptItem.cs.meta new file mode 100644 index 000000000..454f7a016 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8ScriptItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9baa5df97b57b9743bb6c7580e9166ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8Settings.cs b/Unity/Package/Runtime/V8/V8Settings.cs new file mode 100644 index 000000000..44bcb9c30 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Settings.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.ClearScript.V8 +{ + /// + /// Defines properties that comprise ClearScript's V8 configuration. + /// + public static class V8Settings + { + /// + /// Enables or disables Top-Level Await. + /// + /// + /// + /// Top-Level Await + /// enables code at the outermost scope of an + /// ECMAScript 6 + /// module to be executed as an + /// async function. + /// When this feature is enabled, modules can await resources, causing importers to + /// delay evaluation as necessary. + /// + /// + /// To enable Top-Level Await, set this property to true before instantiating + /// or for the first time. Subsequent + /// reassignment will have no effect. + /// + /// + [Obsolete("V8 no longer supports Top-Level Await control. The feature is always enabled.")] + public static bool EnableTopLevelAwait { get; set; } + + /// + /// Gets or sets global V8 options. + /// + /// + /// To override the default global options, set this property before instantiating + /// or for the first time. Subsequent + /// reassignment will have no effect. + /// + public static V8GlobalFlags GlobalFlags { get; set; } + } +} diff --git a/Unity/Package/Runtime/V8/V8Settings.cs.meta b/Unity/Package/Runtime/V8/V8Settings.cs.meta new file mode 100644 index 000000000..49d97a129 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8Settings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 370473a9299c9a9459294f87d934cf83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/V8/V8TestProxy.cs b/Unity/Package/Runtime/V8/V8TestProxy.cs new file mode 100644 index 000000000..0d7ae28e7 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8TestProxy.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.ClearScript.V8.SplitProxy; + +namespace Microsoft.ClearScript.V8 +{ + internal abstract class V8TestProxy : V8Proxy + { + public static V8TestProxy Create() + { + return new V8TestProxyImpl(); + } + + public abstract UIntPtr GetNativeDigest(string value); + + public abstract Statistics GetStatistics(); + + #region Nested type: Statistics + + internal sealed class Statistics + { + public ulong IsolateCount; + public ulong ContextCount; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/V8/V8TestProxy.cs.meta b/Unity/Package/Runtime/V8/V8TestProxy.cs.meta new file mode 100644 index 000000000..af9d95743 --- /dev/null +++ b/Unity/Package/Runtime/V8/V8TestProxy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad6c93f23a157ea43bd4987c3f14b1d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/ValueRef.cs b/Unity/Package/Runtime/ValueRef.cs new file mode 100644 index 000000000..d799f076a --- /dev/null +++ b/Unity/Package/Runtime/ValueRef.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Provides a factory method for . + /// + public static class ValueRef + { + /// + /// Creates a instance with the given value. + /// + /// The value type. + /// The value to assign to the instance. + /// A instance holding the given value. + public static ValueRef Create(T value = default) where T : struct + { + return new ValueRef { Value = value }; + } + } + + /// + /// Holds a value on the heap. + /// + /// The value type. + /// + /// This utility class can be used for passing mutable values to asynchronous methods. + /// + public class ValueRef where T : struct + { + internal ValueRef() + { + } + + /// + /// The value currently held by the instance. + /// + public T Value; + } +} diff --git a/Unity/Package/Runtime/ValueRef.cs.meta b/Unity/Package/Runtime/ValueRef.cs.meta new file mode 100644 index 000000000..7295b34a4 --- /dev/null +++ b/Unity/Package/Runtime/ValueRef.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae0af58c98f1a7b40adfd2baf26792b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Runtime/VoidResult.cs b/Unity/Package/Runtime/VoidResult.cs new file mode 100644 index 000000000..9a159d151 --- /dev/null +++ b/Unity/Package/Runtime/VoidResult.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +namespace Microsoft.ClearScript +{ + /// + /// Represents the result of a host method that returns no value. + /// + /// + /// Some script languages expect every subroutine call to return a value. When script code + /// written in such a language invokes a host method that explicitly returns no value (such + /// as a C# + /// void + /// method), the ClearScript library provides an instance of this class as a dummy return + /// value. + /// + /// + public class VoidResult + { + /// + /// The sole instance of the class. + /// + public static readonly VoidResult Value = new VoidResult(); + + private VoidResult() + { + } + + #region Object overrides + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + /// + /// The version of this method returns "[void]". + /// + public override string ToString() + { + return "[void]"; + } + + #endregion + } +} diff --git a/Unity/Package/Runtime/VoidResult.cs.meta b/Unity/Package/Runtime/VoidResult.cs.meta new file mode 100644 index 000000000..e80527011 --- /dev/null +++ b/Unity/Package/Runtime/VoidResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0aadb4142f35fd04fb9744de49e5df28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests.meta b/Unity/Package/Tests.meta new file mode 100644 index 000000000..af7cc811a --- /dev/null +++ b/Unity/Package/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 147b696d1e7c1ae4ab6fd8afe6a03c03 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime.meta b/Unity/Package/Tests/Runtime.meta new file mode 100644 index 000000000..488843b1e --- /dev/null +++ b/Unity/Package/Tests/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8abdc9e70232bad42aac5f1f63438e66 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef b/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef new file mode 100644 index 000000000..4c7e1c761 --- /dev/null +++ b/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef @@ -0,0 +1,27 @@ +{ + "name": "Decentraland.ClearScript.Tests", + "rootNamespace": "Microsoft.ClearScript.Tests", + "references": [ + "GUID:9659fcb6593e30b46909c1245ed056df" + ], + "includePlatforms": [ + "Editor", + "LinuxStandalone64", + "macOSStandalone", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "Microsoft.CodeAnalysis.dll", + "Microsoft.CSharp.dll", + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef.meta b/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef.meta new file mode 100644 index 000000000..dff847c32 --- /dev/null +++ b/Unity/Package/Tests/Runtime/Decentraland.ClearScript.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b50321a98948f744f8b50465c70c7d5a +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/StdStringTest.cs b/Unity/Package/Tests/Runtime/StdStringTest.cs new file mode 100644 index 000000000..e9b7afa50 --- /dev/null +++ b/Unity/Package/Tests/Runtime/StdStringTest.cs @@ -0,0 +1,17 @@ +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + public sealed class StdStringTest + { + [Test] + public void GetValueTest() + { + using var stdString = new StdString("Bing bong!"); + Assert.That(stdString.Equals("Bing bong!")); + Assert.That(stdString.ToString() == "Bing bong!"); + } + } +} diff --git a/Unity/Package/Tests/Runtime/StdStringTest.cs.meta b/Unity/Package/Tests/Runtime/StdStringTest.cs.meta new file mode 100644 index 000000000..0b601d5ae --- /dev/null +++ b/Unity/Package/Tests/Runtime/StdStringTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1ebf673911a590b44bb302a5f8838701 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs b/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs new file mode 100644 index 000000000..7a76175db --- /dev/null +++ b/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs @@ -0,0 +1,42 @@ +using Microsoft.ClearScript.V8; +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + public class StdV8ValueArrayTest + { + private V8ScriptEngine engine; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + engine = new V8ScriptEngine(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + engine.Dispose(); + } + + [Test] + public void WriteReadInt32() + { + engine.ScriptInvoke(() => + { + using var array = new StdV8ValueArray(5); + + for (int i = 0; i < 5; i++) + array[i].SetInt32(i); + + for (int i = 0; i < 5; i++) + { + var decoded = array[i].Decode(); + Assert.That(decoded.GetInt32(), Is.EqualTo(i)); + } + }); + } + } +} diff --git a/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs.meta b/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs.meta new file mode 100644 index 000000000..aeaa5f0cb --- /dev/null +++ b/Unity/Package/Tests/Runtime/StdV8ValueArrayTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf7f2bdac9d9ab441bea3c82a09ef30e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs b/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs new file mode 100644 index 000000000..5b3604b61 --- /dev/null +++ b/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs @@ -0,0 +1,44 @@ +using Microsoft.ClearScript.V8; +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + public sealed class Uint8ArrayTest + { + private V8ScriptEngine engine; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + engine = new V8ScriptEngine(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + engine.Dispose(); + } + + [Test] + public void CopyTo() + { + engine.AddHostObject("receiveArray", new InvokeHostObject((args, _) => + { + var uint8Array = args[0].GetUint8Array(); + var byteArray = new byte[5]; + uint8Array.CopyTo(byteArray); + Assert.That(byteArray[0], Is.EqualTo(1)); + Assert.That(byteArray[1], Is.EqualTo(2)); + Assert.That(byteArray[2], Is.EqualTo(3)); + Assert.That(byteArray[3], Is.EqualTo(5)); + Assert.That(byteArray[4], Is.EqualTo(7)); + })); + + engine.Execute(@"{ + receiveArray(new Uint8Array([1, 2, 3, 5, 7])); + }"); + } + } +} diff --git a/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs.meta b/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs.meta new file mode 100644 index 000000000..920bd61b9 --- /dev/null +++ b/Unity/Package/Tests/Runtime/Uint8ArrayTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd9c6e77db6d4104c898a5d624eba975 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/V8HostObjectTest.cs b/Unity/Package/Tests/Runtime/V8HostObjectTest.cs new file mode 100644 index 000000000..d2ecaee92 --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8HostObjectTest.cs @@ -0,0 +1,573 @@ +using System; +using System.Globalization; +using System.Numerics; +using Microsoft.ClearScript.V8; +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + internal sealed class V8HostObjectTest + { + private V8ScriptEngine engine; + private HostObject hostObject; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + engine = new V8ScriptEngine(V8ScriptEngineFlags.EnableDateTimeConversion); + hostObject = new HostObject(); + engine.AddHostObject("hostObject", hostObject); + + engine.AddHostObject("assert", new InvokeHostObject((args, _) => + { + if (args.Length != 1) + throw new ArgumentException($"Expected 1 argument, but got {args.Length}"); + + Assert.That(args[0].GetBoolean()); + })); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + engine.Dispose(); + } + + [TearDown] + public void TearDown() + { + hostObject.GetNamedProperty = null; + hostObject.SetNamedProperty = null; + hostObject.DeleteNamedProperty = null; + hostObject.GetIndexedProperty = null; + hostObject.SetIndexedProperty = null; + hostObject.DeleteIndexedProperty = null; + hostObject.GetEnumerator = null; + hostObject.GetAsyncEnumerator = null; + hostObject.GetNamedPropertyNames = null; + hostObject.GetIndexedPropertyIndices = null; + } + + [Test] + public void DeleteIndexedProperty() + { + bool wasCalled = false; + + hostObject.DeleteIndexedProperty = index => + { + wasCalled = true; + Assert.That(index, Is.EqualTo(42)); + return true; + }; + + engine.Execute(@"{ + delete hostObject[42]; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void DeleteNamedProperty() + { + bool wasCalled = false; + + hostObject.DeleteNamedProperty = name => + { + wasCalled = true; + Assert.That(name.Equals("deleteProperty")); + return true; + }; + + engine.Execute(@"{ + delete hostObject.deleteProperty; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void GetBigInt() + { + bool wasCalled = false; + var avogadro = BigInteger.Parse("602200000000000000000000"); + + hostObject.GetNamedProperty = ((StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getBigInt")); + value.SetBigInt(avogadro); + }); + + object result = engine.Evaluate(@"{ + let value = hostObject.getBigInt; + assert(value === 602200000000000000000000n); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo(avogadro)); + } + + [Test] + public void GetBoolean() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getBoolean")); + value.SetBoolean(true); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getBoolean; + assert(value === true); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.True); + } + + [Test] + public void GetDateTime() + { + bool wasCalled = false; + + var ponyEpoch = DateTime.Parse("2010-10-10T20:30:00Z", CultureInfo.InvariantCulture, + DateTimeStyles.AdjustToUniversal); + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getDateTime")); + value.SetDateTime(ponyEpoch); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getDateTime; + assert(value instanceof Date); + let ponyEpoch = new Date('2010-10-10T20:30:00Z'); + assert(value.getTime() === ponyEpoch.getTime()); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo(ponyEpoch)); + } + + [Test] + public void GetHostObject() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getHostObject")); + value.SetHostObject(hostObject); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getHostObject; + assert(value === hostObject); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo(hostObject)); + } + + [Test] + public void GetIndexedProperty() + { + bool wasCalled = false; + + hostObject.GetIndexedProperty = (index, value) => + { + wasCalled = true; + Assert.That(index == 13); + value.SetString("Bing bong!"); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject[13]; + assert(value === 'Bing bong!'); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo("Bing bong!")); + } + + [Test] + public void GetInt32() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getInt32")); + value.SetInt32(-273); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getInt32; + assert(value == -273); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo(-273)); + } + + [Test] + public void GetNull() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getNull")); + value.SetNull(); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getNull; + assert(value === null); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.Null); + } + + [Test] + public void GetNumber() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getNumber")); + value.SetNumber(Math.PI); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getNumber; + assert(value === 3.1415926535897931); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo(Math.PI)); + } + + [Test] + public void GetString() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getString")); + value.SetString("Bing bong!"); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getString; + assert(value ==='Bing bong!'); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.TypeOf()); + Assert.That(result, Is.EqualTo("Bing bong!")); + } + + [Test] + public void GetUndefined() + { + bool wasCalled = false; + + hostObject.GetNamedProperty = (StdString name, V8Value value, out bool isConst) => + { + wasCalled = true; + isConst = false; + Assert.That(name.Equals("getUndefined")); + value.SetUndefined(); + }; + + object result = engine.Evaluate(@"{ + let value = hostObject.getUndefined; + assert(value === undefined); + value; + }"); + + Assert.That(wasCalled); + Assert.That(result, Is.EqualTo(Undefined.Value)); + } + + [Test] + public void SetBigInt() + { + bool wasCalled = false; + var avogadro = BigInteger.Parse("602200000000000000000000"); + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setBigInt")); + Assert.That(value.GetBigInt(), Is.EqualTo(avogadro)); + }; + + engine.Execute(@"{ + hostObject.setBigInt = 602200000000000000000000n; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetBoolean() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setBoolean")); + Assert.That(value.GetBoolean(), Is.True); + }; + + engine.Execute(@"{ + hostObject.setBoolean = true; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetDateTime() + { + bool wasCalled = false; + + var ponyEpoch = DateTime.Parse("2010-10-10T20:30:00Z", CultureInfo.InvariantCulture, + DateTimeStyles.AdjustToUniversal); + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setDateTime")); + Assert.That(value.GetDateTime(), Is.EqualTo(ponyEpoch)); + }; + + engine.Execute(@"{ + hostObject.setDateTime = new Date('2010-10-10T20:30:00Z'); + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetHostObject() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setHostObject")); + Assert.That(value.GetHostObject(), Is.EqualTo(hostObject)); + }; + + engine.Execute(@"{ + hostObject.setHostObject = hostObject; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetIndexedProperty() + { + bool wasCalled = false; + + hostObject.SetIndexedProperty = (index, value) => + { + wasCalled = true; + Assert.That(index, Is.EqualTo(13)); + Assert.That(value.GetString(), Is.EqualTo("Bing bong!")); + }; + + engine.Execute(@"{ + hostObject[13] = 'Bing bong!'; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetNull() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setNull")); + Assert.That(value.Type, Is.EqualTo(V8Value.Type.Null)); + }; + + engine.Execute(@"{ + hostObject.setNull = null; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetNumber() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setNumber")); + Assert.That(value.GetNumber(), Is.EqualTo(Math.PI)); + }; + + engine.Execute(@"{ + hostObject.setNumber = 3.1415926535897931; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetString() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setString")); + Assert.That(value.GetString(), Is.EqualTo("Bing bong!")); + }; + + engine.Execute(@"{ + hostObject.setString = 'Bing bong!'; + }"); + + Assert.That(wasCalled); + } + + [Test] + public void SetUndefined() + { + bool wasCalled = false; + + hostObject.SetNamedProperty = (name, value) => + { + wasCalled = true; + Assert.That(name.Equals("setUndefined")); + Assert.That(value.Type, Is.EqualTo(V8Value.Type.Undefined)); + }; + + engine.Execute(@"{ + hostObject.setUndefined = undefined; + }"); + + Assert.That(wasCalled); + } + + private sealed class HostObject : IV8HostObject + { + public GetNamedPropertyCallback GetNamedProperty; + public SetNamedPropertyCallback SetNamedProperty; + public DeleteNamedPropertyCallback DeleteNamedProperty; + public GetIndexedPropertyCallback GetIndexedProperty; + public SetIndexedPropertyCallback SetIndexedProperty; + public DeleteIndexedPropertyCallback DeleteIndexedProperty; + public GetEnumeratorCallback GetEnumerator; + public GetAsyncEnumeratorCallback GetAsyncEnumerator; + public GetNamedPropertyNamesCallback GetNamedPropertyNames; + public GetIndexedPropertyIndicesCallback GetIndexedPropertyIndices; + + void IV8HostObject.GetNamedProperty(StdString name, V8Value value, out bool isConst) => + GetNamedProperty(name, value, out isConst); + + void IV8HostObject.SetNamedProperty(StdString name, V8Value.Decoded value) => + SetNamedProperty(name, value); + + bool IV8HostObject.DeleteNamedProperty(StdString name) => + DeleteNamedProperty(name); + + void IV8HostObject.GetIndexedProperty(int index, V8Value value) => + GetIndexedProperty(index, value); + + void IV8HostObject.SetIndexedProperty(int index, V8Value.Decoded value) => + SetIndexedProperty(index, value); + + bool IV8HostObject.DeleteIndexedProperty(int index) => + DeleteIndexedProperty(index); + + void IV8HostObject.GetEnumerator(V8Value result) => + GetEnumerator(result); + + void IV8HostObject.GetAsyncEnumerator(V8Value result) => + GetAsyncEnumerator(result); + + void IV8HostObject.GetNamedPropertyNames(StdStringArray names) => + GetNamedPropertyNames(names); + + void IV8HostObject.GetIndexedPropertyIndices(StdInt32Array indices) => + GetIndexedPropertyIndices(indices); + } + + private delegate void GetNamedPropertyCallback(StdString name, V8Value value, out bool isConst); + + private delegate void SetNamedPropertyCallback(StdString name, V8Value.Decoded value); + + private delegate bool DeleteNamedPropertyCallback(StdString name); + + private delegate void GetIndexedPropertyCallback(int index, V8Value value); + + private delegate void SetIndexedPropertyCallback(int index, V8Value.Decoded value); + + private delegate bool DeleteIndexedPropertyCallback(int index); + + private delegate void GetEnumeratorCallback(V8Value result); + + private delegate void GetAsyncEnumeratorCallback(V8Value result); + + private delegate void GetNamedPropertyNamesCallback(StdStringArray names); + + private delegate void GetIndexedPropertyIndicesCallback(StdInt32Array indices); + } +} diff --git a/Unity/Package/Tests/Runtime/V8HostObjectTest.cs.meta b/Unity/Package/Tests/Runtime/V8HostObjectTest.cs.meta new file mode 100644 index 000000000..5756ebec3 --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8HostObjectTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a37388c0309546348a5894a6034ca443 +timeCreated: 1738331406 \ No newline at end of file diff --git a/Unity/Package/Tests/Runtime/V8ObjectTest.cs b/Unity/Package/Tests/Runtime/V8ObjectTest.cs new file mode 100644 index 000000000..89f504a93 --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8ObjectTest.cs @@ -0,0 +1,96 @@ +using Microsoft.ClearScript.V8; +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + public sealed class V8ObjectTest + { + private V8ScriptEngine engine; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + engine = new V8ScriptEngine(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + engine.Dispose(); + } + + [Test] + public new void GetHashCode() + { + engine.Execute("var sameObject = { }"); + var sameObject0 = (ScriptObject)engine.Evaluate("sameObject"); + var sameObject1 = (ScriptObject)engine.Evaluate("sameObject"); + Assume.That(!object.ReferenceEquals(sameObject0, sameObject1)); + + engine.ScriptInvoke(() => + { + var v8Object0 = new V8Object(sameObject0); + var v8Object1 = new V8Object(sameObject1); + Assume.That(v8Object0.ptr != v8Object1.ptr); + Assert.That(v8Object0.GetHashCode() == v8Object1.GetHashCode()); + }); + } + + [Test] + public void GetIndexedProperty() + { + var scriptObject = (ScriptObject)engine.Evaluate("[1, 2, 3]"); + + engine.ScriptInvoke(() => + { + var v8Object = new V8Object(scriptObject); + using var value = V8Value.New(); + + for (int i = 0; i < 3; i++) + { + v8Object.GetIndexedProperty(i, value); + using var decoded = value.Decode(); + Assert.That(decoded.GetNumber(), Is.EqualTo(i + 1.0)); + } + }); + } + + [Test] + public void GetNamedProperty() + { + var scriptObject = (ScriptObject)engine.Evaluate(@"({ + jinxies: 'Bing bong!' + })"); + + engine.ScriptInvoke(() => + { + using var name = new StdString("jinxies"); + using var value = V8Value.New(); + new V8Object(scriptObject).GetNamedProperty(name, value); + using var decoded = value.Decode(); + Assert.That(decoded.GetString(), Is.EqualTo("Bing bong!")); + }); + } + + [Test] + public void Invoke() + { + var scriptObject = (ScriptObject)engine.Evaluate(@"(function(a, b) { + return a + b; + })"); + + engine.ScriptInvoke(() => + { + using var args = new StdV8ValueArray(2); + args[0].SetString("bing"); + args[1].SetString("bong"); + using var result = V8Value.New(); + new V8Object(scriptObject).Invoke(args, result); + using var decoded = result.Decode(); + Assert.That(decoded.GetString(), Is.EqualTo("bingbong")); + }); + } + } +} diff --git a/Unity/Package/Tests/Runtime/V8ObjectTest.cs.meta b/Unity/Package/Tests/Runtime/V8ObjectTest.cs.meta new file mode 100644 index 000000000..289ca1de0 --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8ObjectTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ef3b8b803a42fb4f9a21ad40bf1b96f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/Tests/Runtime/V8ValueTest.cs b/Unity/Package/Tests/Runtime/V8ValueTest.cs new file mode 100644 index 000000000..9a245f9c6 --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8ValueTest.cs @@ -0,0 +1,198 @@ +using System; +using System.Globalization; +using System.Numerics; +using Microsoft.ClearScript.V8; +using Microsoft.ClearScript.V8.SplitProxy; +using NUnit.Framework; + +namespace Microsoft.ClearScript.Tests +{ + [TestFixture, Parallelizable(ParallelScope.Fixtures)] + public class V8ValueTest + { + private V8ScriptEngine engine; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + engine = new V8ScriptEngine(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + engine.Dispose(); + } + + [Test] + public void SetAndGetBigInt() + { + var avogadro = BigInteger.Parse("602200000000000000000000"); + + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetBigInt(avogadro); + var decoded = value.Decode(); + Assert.That(decoded.GetBigInt(), Is.EqualTo(avogadro)); + }); + } + + [Test] + public void SetAndGetBoolean() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetBoolean(true); + var decoded = value.Decode(); + Assert.That(decoded.GetBoolean(), Is.True); + }); + } + + [Test] + public void SetAndGetDateTime() + { + var ponyEpoch = DateTime.Parse("2010-10-10T20:30:00Z", CultureInfo.InvariantCulture, + DateTimeStyles.AdjustToUniversal); + + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetDateTime(ponyEpoch); + var decoded = value.Decode(); + Assert.That(decoded.GetDateTime(), Is.EqualTo(ponyEpoch)); + }); + } + + [Test] + public void SetAndGetHostObject() + { + var hostObject = new HostObject(); + + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetHostObject(hostObject); + var decoded = value.Decode(); + Assert.That(decoded.GetHostObject(), Is.EqualTo(hostObject)); + }); + } + + [Test] + public void SetAndGetInt32() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetInt32(-273); + var decoded = value.Decode(); + Assert.That(decoded.GetInt32(), Is.EqualTo(-273)); + }); + } + + [Test] + public void SetAndGetNull() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetNull(); + var decoded = value.Decode(); + Assert.That(decoded.Type, Is.EqualTo(V8Value.Type.Null)); + }); + } + + [Test] + public void SetAndGetNullHostObject() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetHostObject(null); + var decoded = value.Decode(); + Assert.That(decoded.Type, Is.EqualTo(V8Value.Type.Null)); + }); + } + + [Test] + public void SetAndGetNullString() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetString(null); + var decoded = value.Decode(); + Assert.That(decoded.Type, Is.EqualTo(V8Value.Type.Null)); + }); + } + + [Test] + public void SetAndGetNumber() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetNumber(Math.PI); + var decoded = value.Decode(); + Assert.That(decoded.GetNumber(), Is.EqualTo(Math.PI)); + }); + } + + [Test] + public void SetAndGetString() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetString("Bing bong!"); + var decoded = value.Decode(); + Assert.That(decoded.GetString(), Is.EqualTo("Bing bong!")); + }); + } + + [Test] + public void SetAndGetUInt32() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetUInt32(uint.MaxValue); + var decoded = value.Decode(); + Assert.That(decoded.GetUInt32(), Is.EqualTo(uint.MaxValue)); + }); + } + + [Test] + public void SetAndGetUndefined() + { + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetUndefined(); + var decoded = value.Decode(); + Assert.That(decoded.Type, Is.EqualTo(V8Value.Type.Undefined)); + }); + } + + [Test] + public void SetAndGetV8Object() + { + var scriptObject = (ScriptObject)engine.Evaluate("({ })"); + + engine.ScriptInvoke(() => + { + using var value = V8Value.New(); + value.SetV8Object(scriptObject); + using var decoded = value.Decode(); + + Assert.That(decoded.GetV8Object().GetHashCode(), + Is.EqualTo(scriptObject.GetHashCode())); + }); + } + + private sealed class HostObject : IV8HostObject + { + } + } +} \ No newline at end of file diff --git a/Unity/Package/Tests/Runtime/V8ValueTest.cs.meta b/Unity/Package/Tests/Runtime/V8ValueTest.cs.meta new file mode 100644 index 000000000..e1954a37a --- /dev/null +++ b/Unity/Package/Tests/Runtime/V8ValueTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d71c169ad56440f46b4a047060169b0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Package/package.json b/Unity/Package/package.json new file mode 100644 index 000000000..aa837513e --- /dev/null +++ b/Unity/Package/package.json @@ -0,0 +1,26 @@ +{ + "name": "org.decentraland.clearscript", + "version": "7.4.5", + "description": "This is a fork of Microsoft's ClearScript library, which itself is a wrapper around Google's V8 JavaScript engine. Besides being packaged for Unity, this version of ClearScript offers an additional unsafe, mostly alloc-free V8 API.", + "displayName": "ClearScript", + "unity": "2022.3", + "author": { + "name": "Decentraland", + "email": "hello@decentraland.org", + "url": "https://decentraland.org" + }, + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.2.1" + }, + "documentationUrl": "https://github.com/decentraland/ClearScript", + "keywords": [ + "clearscript", + "javascript", + "jscript", + "v8", + "vbscript", + "webassembly" + ], + "license": "MIT", + "licensesUrl": "https://github.com/decentraland/ClearScript/blob/master/License.txt" +} diff --git a/Unity/Package/package.json.meta b/Unity/Package/package.json.meta new file mode 100644 index 000000000..aa3ec2b89 --- /dev/null +++ b/Unity/Package/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 34f1d2039ee53854c9ae05c153a16689 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/PackageBuilder/PackageBuilder.csproj b/Unity/PackageBuilder/PackageBuilder.csproj new file mode 100644 index 000000000..90911abb2 --- /dev/null +++ b/Unity/PackageBuilder/PackageBuilder.csproj @@ -0,0 +1,9 @@ + + + net8.0 + disable + enable + nullable + Exe + + diff --git a/Unity/PackageBuilder/Program.cs b/Unity/PackageBuilder/Program.cs new file mode 100644 index 000000000..02fd14705 --- /dev/null +++ b/Unity/PackageBuilder/Program.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +try +{ + string srcPath = @"..\..\..\..\..\ClearScript"; + string dstPath = @"..\..\..\..\Package\Runtime"; + + foreach (string file in Directory.GetFiles(dstPath, "*.cs", SearchOption.AllDirectories)) + { + File.Delete(file); + } + + foreach (string file in Directory.GetFiles(srcPath, "*.cs", SearchOption.AllDirectories)) + { + if (file.Contains(@"\ICUData\") + || file.Contains(@"\Properties\") && !file.EndsWith(@"\AssemblyInfo.Core.cs") + || file.Contains(@"\Windows\") + || file.Contains(".Net5.") + || file.Contains(".NetCore.") + || file.Contains(".NetFramework.") + || file.Contains(".UWP.") + || file.Contains(".Windows.")) + { + continue; + } + + string dstFile = string.Concat(dstPath, file.AsSpan(srcPath.Length)); + Directory.CreateDirectory(Path.GetDirectoryName(dstFile)!); + + if (file.EndsWith(@"\AssemblyInfo.Core.cs")) + { + using var reader = new StreamReader(file); + using var writer = new StreamWriter(dstFile); + writer.NewLine = "\n"; + + while (true) + { + string? line = reader.ReadLine(); + + if (line == null) + goto endOfFile; + + if (line.StartsWith("[assembly: InternalsVisibleTo(")) + break; + + writer.WriteLine(line); + } + + writer.WriteLine(@"[assembly: InternalsVisibleTo(""Decentraland.ClearScript.Tests"")]"); + + while (true) + { + string? line = reader.ReadLine(); + + if (line == null) + goto endOfFile; + + if (!line.StartsWith("[assembly: InternalsVisibleTo(")) + { + writer.WriteLine(line); + break; + } + } + + while (true) + { + string? line = reader.ReadLine(); + + if (line == null) + goto endOfFile; + + writer.WriteLine(line); + } + + endOfFile:; + } + else if (file.EndsWith(@"\V8SplitProxyManaged.cs")) + { + using var reader = new StreamReader(file); + using var writer = new StreamWriter(dstFile); + writer.NewLine = "\n"; + var methods = new Dictionary(); + + while (true) + { + string? line = reader.ReadLine(); + + if (line == null) + break; + + { + Match match = Regex.Match(line, @"\bGetMethodPair<(\w+)>\((\w+)\)"); + + if (match.Success) + { + string delegateType = match.Groups[1].Value; + string method = match.Groups[2].Value; + methods.Add(method, delegateType); + } + } + + { + Match match = Regex.Match(line, @"^(\s*)private static \w+ (\w+)\([^)]*\)"); + + if (match.Success) + { + string method = match.Groups[2].Value; + + if (methods.TryGetValue(method, out string? delegateType)) + { + writer.Write(match.Groups[1].Value); + writer.Write("[AOT.MonoPInvokeCallback(typeof("); + writer.Write(delegateType); + writer.WriteLine("))]"); + } + } + } + + writer.WriteLine(line); + } + } + else + { + File.Copy(file, dstFile); + } + } + + DeleteEmptyFolders(dstPath); +} +catch (Exception ex) +{ + Console.WriteLine(ex); + Console.ReadKey(true); + throw; +} + +// TODO: Write tests in MSTest and convert them to NUnit. +/*try +{ + string srcPath = @"..\..\..\..\..\ClearScriptTest"; + string dstPath = @"..\..\..\..\Package\Tests\Runtime"; + + foreach (string file in Directory.GetFiles(dstPath, "*.cs", SearchOption.AllDirectories)) + { + File.Delete(file); + } + + foreach (string file in Directory.GetFiles(srcPath, "*.cs", SearchOption.AllDirectories)) + { + if (file.Contains(".NetCore.") + || file.Contains(".NetFramework.")) + { + continue; + } + + string dstFile = string.Concat(dstPath, file.AsSpan(srcPath.Length)); + Directory.CreateDirectory(Path.GetDirectoryName(dstFile)!); + using var reader = new StreamReader(file); + using var writer = new StreamWriter(dstFile); + writer.NewLine = "\n"; + + while (true) + { + string? line = reader.ReadLine(); + + if (line == null) + break; + else if (line == "using Microsoft.VisualStudio.TestTools.UnitTesting;") + writer.WriteLine("using NUnit.Framework;"); + else if (line == " [TestClass]") + writer.WriteLine(" [TestFixture]"); + else if (line == " [TestInitialize]") + writer.WriteLine(" [SetUp]"); + else if (line == " [TestCleanup]") + writer.WriteLine(" [TearDown]"); + else if (line.StartsWith(" [TestMethod, TestCategory(\"")) + writer.WriteLine(" [Test]"); + else + writer.WriteLine(line); + } + } + + DeleteEmptyFolders(dstPath); +} +catch (Exception ex) +{ + Console.WriteLine(ex); + Console.ReadKey(true); + throw; +}*/ + +static void DeleteEmptyFolders(string path) +{ + foreach (string metaFile in Directory.GetFiles(path, "*.meta", SearchOption.AllDirectories)) + { + string fileOrFolder = metaFile[..^".meta".Length]; + + if (File.Exists(fileOrFolder)) + continue; + + if (Directory.Exists(fileOrFolder)) + { + string[] files = Directory.GetFiles(fileOrFolder, "", SearchOption.AllDirectories); + + if (files.Any(i => !i.EndsWith(".meta"))) + continue; + + // Delete meta files of directories that contain nothing but meta files. These directories + // will then become empty and eligible for deletion in the next step. + } + + File.Delete(metaFile); + } + + foreach (string folder in Directory.GetDirectories(path, "", SearchOption.AllDirectories)) + { + try + { + if (Directory.GetFiles(folder, "", SearchOption.AllDirectories).Length == 0) + Directory.Delete(folder, true); + } + catch (DirectoryNotFoundException) { } + } +}