├── .circleci └── config.yml ├── .gitattributes ├── .github ├── FUNDING.yml ├── actions │ ├── build-node │ │ └── action.yml │ ├── build │ │ └── action.yml │ ├── create-test-report │ │ └── action.yml │ ├── setup-env │ │ └── action.yml │ └── test-build │ │ └── action.yml └── workflows │ ├── build-all.yml │ ├── build.yml │ ├── ci-old.yml │ └── ci.yml ├── .gitignore ├── .npmignore ├── Dockerfile ├── EdgeJs.sln ├── LICENSE ├── README.md ├── appveyor.ps1 ├── appveyor_disable.yml ├── appveyor_double.yml ├── binding.gyp ├── edge-js.d.ts ├── lib ├── bootstrap │ ├── .gitignore │ ├── Dummy.cs │ └── bootstrap.csproj ├── double_edge.js ├── edge.js └── native │ ├── darwin │ ├── arm64 │ │ ├── 18 │ │ │ ├── MonoEmbedding.exe │ │ │ ├── edge_coreclr.node │ │ │ ├── edge_nativeclr.node │ │ │ └── node.version │ │ ├── 20 │ │ │ ├── MonoEmbedding.exe │ │ │ ├── edge_coreclr.node │ │ │ ├── edge_nativeclr.node │ │ │ └── node.version │ │ ├── 22 │ │ │ ├── MonoEmbedding.exe │ │ │ ├── edge_coreclr.node │ │ │ ├── edge_nativeclr.node │ │ │ └── node.version │ │ └── 24 │ │ │ ├── MonoEmbedding.exe │ │ │ ├── edge_coreclr.node │ │ │ ├── edge_nativeclr.node │ │ │ └── node.version │ └── x64 │ │ ├── 18 │ │ ├── MonoEmbedding.exe │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ │ ├── 20 │ │ ├── MonoEmbedding.exe │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ │ ├── 22 │ │ ├── MonoEmbedding.exe │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ │ └── 24 │ │ ├── MonoEmbedding.exe │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ └── win32 │ ├── arm64 │ ├── 20 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── 22 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── 24 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── concrt140.dll │ ├── msvcp140.dll │ ├── vccorlib140.dll │ └── vcruntime140.dll │ ├── ia32 │ ├── 18 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── 20 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── 22 │ │ ├── edge_coreclr.node │ │ ├── edge_nativeclr.node │ │ └── node.version │ ├── concrt140.dll │ ├── msvcp140.dll │ ├── vccorlib140.dll │ └── vcruntime140.dll │ └── x64 │ ├── 18 │ ├── edge_coreclr.node │ ├── edge_nativeclr.node │ └── node.version │ ├── 20 │ ├── edge_coreclr.node │ ├── edge_nativeclr.node │ └── node.version │ ├── 22 │ ├── edge_coreclr.node │ ├── edge_nativeclr.node │ └── node.version │ ├── 24 │ ├── edge_coreclr.node │ ├── edge_nativeclr.node │ └── node.version │ ├── concrt140.dll │ ├── msvcp140.dll │ ├── vccorlib140.dll │ └── vcruntime140.dll ├── package-lock.json ├── package.json ├── performance ├── .gitignore ├── BookService │ ├── App.config │ ├── BookService.csproj │ ├── BookService.sln │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── compile.sh │ └── packages.config ├── latency.js ├── marshal_clr2v8.js └── performance.cs ├── samples ├── 101_hello_lambda.js ├── 102_hello_function.js ├── 103_hello_file.csx ├── 103_hello_file.js ├── 104_add7_class.js ├── 105_add7_dll.js ├── 106_marshal_v82clr.js ├── 107_marshal_clr2v8.js ├── 108_func.js ├── 108_lambda.js ├── 109_sync.js ├── 110_clr_instance.js ├── 111_clr_listener.js ├── 201_worker.js ├── 202_sql.csx ├── 202_sql.js ├── 203_x509store.js ├── 204_event_log.js ├── 205_soap.csx ├── 205_soap.js ├── 206_registry_read.js ├── 206_registry_write.js ├── 207_unzip.js ├── 207_zip.js ├── 208_convertImage.js ├── 209_websocket.js ├── 210_windows_authentication.js ├── 211_events.js ├── 301_cspyfsps.js ├── edge.png └── readme.txt ├── src ├── CoreCLREmbedding │ ├── coreclrembedding.cpp │ ├── coreclrfunc.cpp │ ├── coreclrfuncinvokecontext.cpp │ ├── coreclrnodejsfunc.cpp │ ├── coreclrnodejsfuncinvokecontext.cpp │ ├── cpprest │ │ └── include │ │ │ ├── asyncrt_utils.h │ │ │ └── json.h │ ├── deps │ │ ├── deps_entry.cpp │ │ ├── deps_entry.h │ │ ├── deps_format.cpp │ │ ├── deps_format.h │ │ ├── deps_resolver.cpp │ │ └── deps_resolver.h │ ├── edge.h │ ├── fxr │ │ ├── fx_muxer.cpp │ │ ├── fx_muxer.h │ │ ├── fx_ver.cpp │ │ └── fx_ver.h │ ├── host │ │ ├── args.cpp │ │ ├── args.h │ │ ├── coreclr.cpp │ │ ├── coreclr.h │ │ ├── error_codes.h │ │ ├── libhost.cpp │ │ ├── libhost.h │ │ ├── runtime_config.cpp │ │ └── runtime_config.h │ ├── json │ │ └── casablanca │ │ │ ├── LICENSE.txt │ │ │ ├── include │ │ │ ├── cpprest │ │ │ │ ├── asyncrt_utils.h │ │ │ │ ├── details │ │ │ │ │ ├── SafeInt3.hpp │ │ │ │ │ ├── basic_types.h │ │ │ │ │ ├── cpprest_compat.h │ │ │ │ │ └── nosal.h │ │ │ │ └── json.h │ │ │ ├── pplx │ │ │ │ ├── pplx.h │ │ │ │ ├── pplxcancellation_token.h │ │ │ │ ├── pplxconv.h │ │ │ │ ├── pplxinterface.h │ │ │ │ ├── pplxlinux.h │ │ │ │ ├── pplxtasks.h │ │ │ │ ├── pplxwin.h │ │ │ │ └── threadpool.h │ │ │ └── stdafx.h │ │ │ └── src │ │ │ ├── json │ │ │ ├── json.cpp │ │ │ ├── json_parsing.cpp │ │ │ └── json_serialization.cpp │ │ │ └── utilities │ │ │ └── asyncrt_utils.cpp │ └── pal │ │ ├── pal.h │ │ ├── pal.unix.cpp │ │ ├── pal.windows.cpp │ │ ├── pal_utils.cpp │ │ ├── pal_utils.h │ │ ├── trace.cpp │ │ └── trace.h ├── common │ ├── callbackhelper.cpp │ ├── clrfuncreflectionwrap.cs │ ├── edge.cpp │ ├── edge_common.h │ ├── utils.cpp │ └── v8synchronizationcontext.cpp ├── dotnet │ ├── clractioncontext.cpp │ ├── clrfunc.cpp │ ├── clrfuncinvokecontext.cpp │ ├── clrfuncreflectionwrap.cpp │ ├── edge.h │ ├── nodejsfunc.cpp │ ├── nodejsfuncinvokecontext.cpp │ ├── persistentdisposecontext.cpp │ └── utils.cpp ├── double │ └── Edge.js │ │ ├── Edge.js.csproj │ │ ├── dotnet │ │ └── EdgeJs.cs │ │ └── dotnetcore │ │ ├── coreclrembedding.cs │ │ ├── nodejsfunc.cs │ │ ├── nodejsfuncinvokecontext.cs │ │ └── semversion.cs └── mono │ ├── clractioncontext.cpp │ ├── clrfunc.cpp │ ├── clrfuncinvokecontext.cpp │ ├── clrfuncinvokecontext.cs │ ├── dictionary.cpp │ ├── edge.h │ ├── monoembedding.cpp │ ├── monoembedding.cs │ ├── nodejsfunc.cpp │ ├── nodejsfunc.cs │ ├── nodejsfuncinvokecontext.cpp │ ├── nodejsfuncinvokecontext.cs │ ├── task.cpp │ └── utils.cpp ├── stress └── test.js ├── test ├── 101_edge_func.js ├── 102_node2net.js ├── 103_net2node.js ├── 104_csx.js ├── 105_node2net_sync.js ├── 106_node2net_symbols.js ├── 201_patterns.js ├── 202_serialization.js ├── config.json ├── configCI.json ├── double │ ├── .gitignore │ ├── double_stress │ │ ├── App.config │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── double_stress.csproj │ │ ├── double_stress.sln │ │ └── packages.config │ └── double_test │ │ ├── DoubleEdge.cs │ │ ├── double_test.csproj │ │ └── double_test.sln ├── hello_class.cs ├── hello_class.csx ├── hello_lambda.csx ├── test.csproj └── tests.cs └── tools ├── build.bat ├── build_double.bat ├── checkMono.js ├── checkplatform.js ├── download.js ├── download_double.js ├── getVersion.js ├── getVersionAction.js ├── install.js ├── nuget ├── README.md ├── build │ └── EdgeJs.targets ├── edge.nuspec └── tools │ └── install.ps1 ├── test.js └── whereis.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | node: circleci/node@6 4 | win: circleci/windows@5.0 5 | macos: circleci/macos@2.4.1 6 | 7 | executors: 8 | node: 9 | docker: 10 | - image: cimg/node:20.12.2 11 | resource_class: medium 12 | windows: 13 | machine: 14 | image: windows-server-2022-gui:current 15 | resource_class: windows.medium 16 | macos: 17 | macos: 18 | xcode: 15.2.0 19 | linux-arm: 20 | docker: 21 | - image: cimg/base:current 22 | resource_class: arm.medium 23 | linux: 24 | docker: 25 | - image: cimg/base:current 26 | resource_class: medium 27 | 28 | refs: 29 | steps: 30 | - &InstallNode 31 | node/install: 32 | node-version: << parameters.node-version >> 33 | - &InstallDotnet 34 | run: 35 | shell: bash 36 | name: Install dotnet 37 | command: | 38 | if [[ $OSTYPE == darwin* ]]; then 39 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 40 | brew install --cask dotnet-sdk 41 | elif [[ $OSTYPE == linux* ]]; then 42 | wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 43 | sudo dpkg -i packages-microsoft-prod.deb 44 | sudo apt-get update 45 | sudo apt-get install -y dotnet-sdk-8.0 46 | sudo rm packages-microsoft-prod.deb 47 | fi 48 | - &Versions 49 | run: 50 | name: Versions 51 | command: node -v && npm -v && dotnet --version && node -p process.platform && node -p process.arch 52 | - &NpmInstall 53 | run: 54 | name: NPM Install 55 | command: npm install 56 | - &Test 57 | run: 58 | shell: bash 59 | name: Test 60 | command: | 61 | if [[ $OSTYPE == darwin* || $OSTYPE == linux* ]]; then 62 | node tools/test.js circleci 63 | else 64 | node tools/test.js circleci 65 | node tools/test.js circleci coreclr 66 | fi 67 | 68 | jobs: 69 | test-node: 70 | # Install node dependencies and run tests 71 | # executor: win/default 72 | parameters: 73 | os: 74 | type: executor 75 | node-version: 76 | type: string 77 | executor: << parameters.os >> 78 | steps: 79 | - checkout 80 | - restore_cache: 81 | keys: 82 | - v1-deps-{{ arch }}-{{ checksum "package-lock.json" }} 83 | - *InstallDotnet 84 | # - node/install-packages: 85 | # cache-path: ~/project/node_modules 86 | # override-ci-command: npm install 87 | - *InstallNode 88 | - *Versions 89 | - run: npm install 90 | - save_cache: 91 | key: v1-deps-{{ arch }}-{{ checksum "package-lock.json" }} 92 | paths: 93 | - node_modules 94 | - *Test 95 | # - run: 96 | # name: Run tests 97 | # command: EDGE_USE_CORECLR=1 node tools/test.js circleci --passWithNoTests 98 | - store_test_results: 99 | path: ./junit 100 | - store_artifacts: 101 | path: ./mochawesome.json 102 | destination: mochawesome.json 103 | 104 | workflows: 105 | build-and-test-linux: 106 | jobs: 107 | - test-node: 108 | matrix: 109 | parameters: 110 | # os: ['linux', 'linux-arm', 'macos'] 111 | os: ['linux', 'linux-arm'] 112 | node-version: ['14', '16' ] 113 | 114 | build-and-test-macos: 115 | jobs: 116 | - test-node: 117 | matrix: 118 | parameters: 119 | # os: ['linux', 'linux-arm', 'macos'] 120 | os: ['macos'] 121 | node-version: ['20', '22'] 122 | 123 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [agracio] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /.github/actions/build/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Build Windows binaries' 2 | description: 'Build Windows binaries' 3 | inputs: 4 | node: 5 | description: 'Node version' 6 | required: true 7 | node-major: 8 | description: 'Node major version' 9 | required: true 10 | arch: 11 | description: 'Target arch' 12 | required: true 13 | 14 | runs: 15 | using: "composite" 16 | steps: 17 | 18 | - name: Build ${{ inputs.arch }} 19 | shell: pwsh 20 | run: | 21 | 22 | node-gyp configure --target=${{ inputs.node }} --runtime=node --release --arch=${{ inputs.arch }} 23 | 24 | if ( '${{ inputs.arch }}' -eq 'arm64' -And '${{ runner.os }}' -eq 'Windows'){ 25 | (Get-Content -Raw build/build_managed.vcxproj) -replace 'Strict', '' | Out-File -Encoding Utf8 build/build_managed.vcxproj 26 | (Get-Content -Raw build/edge_coreclr.vcxproj) -replace 'Strict', '' | Out-File -Encoding Utf8 build/edge_coreclr.vcxproj 27 | (Get-Content -Raw build/edge_nativeclr.vcxproj) -replace 'Strict', '' | Out-File -Encoding Utf8 build/edge_nativeclr.vcxproj 28 | } 29 | 30 | node-gyp build 31 | 32 | if ( '${{ runner.os }}' -eq 'Windows'){ 33 | cmd /c copy /y build\Release\edge_*.node release\win32\${{ inputs.arch }}\${{ inputs.node-major }} 34 | cmd /c rmdir /S /Q build 35 | } 36 | 37 | if ( '${{ runner.os }}' -eq 'macOS'){ 38 | Get-ChildItem -Path build/Release 39 | Copy-Item "build/Release/edge_coreclr.node" -Destination "release/darwin/${{ inputs.arch }}/${{ inputs.node-major }}" 40 | Copy-Item "build/Release/edge_nativeclr.node" -Destination "release/darwin/${{ inputs.arch }}/${{ inputs.node-major }}" 41 | Copy-Item "build/Release/MonoEmbedding.exe" -Destination "release/darwin/${{ inputs.arch }}/${{ inputs.node-major }}" 42 | 43 | node-gyp clean 44 | } 45 | -------------------------------------------------------------------------------- /.github/actions/create-test-report/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Test report' 2 | description: 'Create test report' 3 | inputs: 4 | name: 5 | description: 'name' 6 | required: false 7 | default: 'test-results' 8 | node: 9 | description: 'Node.js version' 10 | required: true 11 | os: 12 | description: 'runs-on' 13 | required: true 14 | 15 | runs: 16 | using: "composite" 17 | steps: 18 | 19 | - name: Read mochawesome.json 20 | uses: actions/github-script@v7 21 | with: 22 | result-encoding: string 23 | script: | 24 | try { 25 | const fs = require('fs') 26 | const jsonString = fs.readFileSync('mochawesome.json') 27 | var report = JSON.parse(jsonString); 28 | let stats = { 29 | passing: report.stats.passes, 30 | skipped: report.stats.pending, 31 | failures: report.stats.failures 32 | }; 33 | core.notice(JSON.stringify(stats)); 34 | } catch(err) { 35 | core.error("Error while reading or parsing mochawesome.json") 36 | core.setFailed(err) 37 | } 38 | 39 | - name: Upload artifacts 40 | uses: actions/upload-artifact@v4 41 | if: success() 42 | with: 43 | name: ${{ inputs.name }}-${{ inputs.os }}-${{ inputs.node }} 44 | path: | 45 | test-results.xml 46 | mochawesome.json 47 | mochawesome.html 48 | assets/ 49 | 50 | # - name: Create test report 51 | # uses: phoenix-actions/test-reporting@v15 52 | # if: success() 53 | # with: 54 | # name: ${{ inputs.name }}-${{ inputs.os }}-node-${{ inputs.node }} 55 | # fail-on-error: true 56 | # path: mochawesome.json # Path to test results 57 | # reporter: mochawesome-json 58 | -------------------------------------------------------------------------------- /.github/actions/setup-env/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup environment' 2 | description: 'Sets up environment' 3 | inputs: 4 | node: 5 | description: 'Node.js version' 6 | required: true 7 | os: 8 | description: 'runs-on' 9 | required: true 10 | arch: 11 | description: 'Architecture' 12 | required: false 13 | default: '' 14 | 15 | runs: 16 | using: "composite" 17 | steps: 18 | 19 | - name: Setup NodeJS 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ inputs.node }} 23 | architecture: ${{ inputs.arch }} 24 | cache: 'npm' 25 | cache-dependency-path: package-lock.json 26 | 27 | - name: Cache node-gyp Linux 28 | if: runner.os == 'Linux' 29 | uses: actions/cache@v4 30 | env: 31 | cache-name: cache-node-gyp 32 | with: 33 | path: ~/.cache/node-gyp 34 | key: '${{ inputs.os }}-${{ inputs.node}}' 35 | 36 | - name: Cache node-gyp macOs 37 | if: runner.os == 'macOS' 38 | uses: actions/cache@v4 39 | env: 40 | cache-name: cache-node-gyp 41 | with: 42 | path: ~/Library/Caches/node-gyp 43 | key: '${{ inputs.os }}-${{ inputs.node}}' 44 | 45 | - if: runner.os == 'macOS' && inputs.node == 16 46 | shell: bash 47 | name: Add missing packages for macOS NodeJs 16 48 | run: | 49 | pip install setuptools 50 | 51 | - name: Cache node modules 52 | id: cache-nodemodules 53 | uses: actions/cache@v4 54 | env: 55 | cache-name: cache-node-modules 56 | with: 57 | path: node_modules 58 | key: ${{ inputs.os }}-${{ inputs.node }}-${{ hashFiles('package-lock.json') }} 59 | 60 | - name: Setup dotnet 61 | uses: actions/setup-dotnet@v4 62 | with: 63 | dotnet-version: '8.0.x' # SDK Version to use; x will use the latest version of the 8.0 channel 64 | 65 | - name: Setup Mono 66 | if: runner.os == 'macOS' 67 | shell: bash 68 | run: | 69 | brew install mono --overwrite 70 | brew reinstall pkg-config 71 | 72 | - name: Setup Mono 73 | if: runner.os == 'Linux' 74 | shell: bash 75 | run: | 76 | sudo apt -q install mono-complete pkg-config libglib2.0-dev 77 | 78 | - name: Versions 79 | shell: bash 80 | run: | 81 | node -v && npm -v && dotnet --version && node -p process.platform && node -p process.arch 82 | 83 | - name: npm install 84 | shell: bash 85 | run: npm i 86 | env: 87 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | build-version: 7 | description: 'Node.js version to build' 8 | required: true 9 | default: '20' 10 | type: choice 11 | options: 12 | - 18 13 | - 20 14 | - 22 15 | - 24 16 | 17 | env: 18 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 19 | DOTNET_NOLOGO: 1 20 | 21 | jobs: 22 | build: 23 | runs-on: ${{ matrix.os }} 24 | # outputs: 25 | # node-version: ${{ steps.node-test-version.outputs.node-version }} 26 | strategy: 27 | matrix: 28 | # os: [windows-2025] 29 | os: [windows-2025, macos-13, macos-15] 30 | fail-fast: true 31 | 32 | name: build node-${{ inputs.build-version }} ${{ matrix.os }} 33 | steps: 34 | 35 | - name: Checkout code 36 | uses: actions/checkout@v4 37 | 38 | - name: Build Node ${{ inputs.build-version }} 39 | uses: ./.github/actions/build-node 40 | with: 41 | node: ${{ inputs.build-version }} 42 | os: ${{ matrix.os }} 43 | 44 | upload-artifacts: 45 | runs-on: ubuntu-latest 46 | needs: test 47 | strategy: 48 | fail-fast: false 49 | 50 | name: upload artifacts node-${{ inputs.build-version }} 51 | steps: 52 | 53 | - name: Download artifacts 54 | uses: actions/download-artifact@v4 55 | if: success() 56 | with: 57 | path: release 58 | pattern: win32-edge-js* 59 | 60 | - name: Download artifacts 61 | uses: actions/download-artifact@v4 62 | with: 63 | path: release 64 | pattern: darwin-edge-js* 65 | 66 | - name: Upload artifacts 67 | uses: actions/upload-artifact/merge@v4 68 | if: success() 69 | with: 70 | name: edge-js-${{ inputs.build-version }} 71 | 72 | test: 73 | runs-on: ${{ matrix.os }} 74 | needs: build 75 | strategy: 76 | matrix: 77 | # os: [windows-2025, windows-11-arm] 78 | os: [windows-2025, windows-11-arm, macos-13, macos-15] 79 | fail-fast: false 80 | 81 | name: test node-${{ inputs.build-version }} ${{ matrix.os }} 82 | steps: 83 | 84 | - name: Checkout code 85 | uses: actions/checkout@v4 86 | 87 | - name: Test build 88 | uses: ./.github/actions/test-build 89 | with: 90 | node: ${{ inputs.build-version }} 91 | os: ${{ matrix.os }} -------------------------------------------------------------------------------- /.github/workflows/ci-old.yml: -------------------------------------------------------------------------------- 1 | name: CI out of support 2 | 3 | on: 4 | workflow_dispatch: 5 | # pull_request: 6 | # paths-ignore: 7 | # - 'samples/*' 8 | # - 'stress/*' 9 | # - 'performance/*' 10 | # - '.github/FUNDING.YML' 11 | # - '.github/workflows/ci.yml' 12 | # - '.github/workflows/build.yml' 13 | # - '.github/workflows/build*.yml' 14 | # - '.github/actions/test-build/action.yml' 15 | # - '.github/actions/build*/*.*' 16 | # - '.github/actions/build/*.*' 17 | # - '**/*.md' 18 | # - '**/*.d.ts' 19 | # - '**/*.bat' 20 | # - '.travis.yml' 21 | # - 'Dockerfile' 22 | # - '.gitconfig' 23 | # - '.gitignore' 24 | # - 'appveyor*.*' 25 | # - 'LICENSE*' 26 | # - '.idea/**' 27 | # - '.vscode/**' 28 | # - '*.bat' 29 | # - '*.nuspec' 30 | # - 'tools/nuget/*' 31 | # - '.npmignore' 32 | # - 'test/config.json' 33 | # - 'test/double' 34 | # - '.circleci' 35 | # - '.circleci/*' 36 | # - 'README.md' 37 | # - '*.sln' 38 | # - '*.vcxproj' 39 | # push: 40 | # branches-ignore: 41 | # - 'circleci' 42 | # paths-ignore: 43 | # - 'samples/*' 44 | # - 'stress/*' 45 | # - 'performance/*' 46 | # - '.github/FUNDING.YML' 47 | # - '.github/workflows/ci.yml' 48 | # - '.github/workflows/build.yml' 49 | # - '.github/workflows/build*.yml' 50 | # - '.github/actions/test-build/action.yml' 51 | # - '.github/actions/build*/*.*' 52 | # - '.github/actions/build/*.*' 53 | # - '**/*.md' 54 | # - '**/*.d.ts' 55 | # - '**/*.bat' 56 | # - '.travis.yml' 57 | # - 'Dockerfile' 58 | # - '.gitconfig' 59 | # - '.gitignore' 60 | # - 'appveyor*.*' 61 | # - 'LICENSE*' 62 | # - '.idea/**' 63 | # - '.vscode/**' 64 | # - '*.bat' 65 | # - '*.nuspec' 66 | # - 'tools/nuget/*' 67 | # - '.npmignore' 68 | # - 'test/config.json' 69 | # - 'test/double' 70 | # - '.circleci' 71 | # - '.circleci/*' 72 | # - 'README.md' 73 | # - '*.sln' 74 | # - '*.vcxproj' 75 | 76 | env: 77 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true # required to setup CSC 78 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 79 | DOTNET_NOLOGO: 1 80 | 81 | jobs: 82 | test: 83 | runs-on: ${{ matrix.os }} 84 | name: test-${{ matrix.os }}-node-${{ matrix.node }} 85 | strategy: 86 | fail-fast: false 87 | matrix: 88 | os: [macos-13, macos-14, ubuntu-24.04, ubuntu-24.04-arm] 89 | node: [16] 90 | steps: 91 | 92 | - name: Checkout code 93 | uses: actions/checkout@v4 94 | 95 | - name: Setup env 96 | uses: ./.github/actions/setup-env 97 | with: 98 | node: ${{ matrix.node }} 99 | os: ${{ matrix.os }} 100 | 101 | - name: Run .NET 4.5 tests 102 | shell: bash 103 | run: node tools/test.js CI 104 | 105 | - name: "Run .net core tests" 106 | run: node tools/test.js CI 107 | env: 108 | EDGE_USE_CORECLR: 1 109 | 110 | - name: Test report 111 | uses: ./.github/actions/create-test-report 112 | with: 113 | node: ${{ matrix.node }} 114 | os: ${{ matrix.os }} 115 | 116 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | paths-ignore: 7 | - 'samples/*' 8 | - 'stress/*' 9 | - 'performance/*' 10 | - '.github/FUNDING.YML' 11 | - '.github/workflows/ci-old.yml' 12 | - '.github/workflows/build.yml' 13 | - '.github/workflows/build*.yml' 14 | - '.github/actions/test-build/action.yml' 15 | - '.github/actions/build*/*.*' 16 | - '.github/actions/build/*.*' 17 | - '**/*.md' 18 | - '**/*.d.ts' 19 | - '**/*.bat' 20 | - '.travis.yml' 21 | - 'Dockerfile' 22 | - '.gitconfig' 23 | - '.gitignore' 24 | - 'appveyor*.*' 25 | - 'LICENSE*' 26 | - '.idea/**' 27 | - '.vscode/**' 28 | - '*.bat' 29 | - '*.nuspec' 30 | - 'tools/nuget/*' 31 | - '.npmignore' 32 | - 'test/config.json' 33 | - 'test/double' 34 | - '.circleci' 35 | - '.circleci/*' 36 | - 'README.md' 37 | - '*.sln' 38 | - '*.vcxproj' 39 | push: 40 | branches-ignore: 41 | - 'circleci' 42 | paths-ignore: 43 | - 'samples/*' 44 | - 'stress/*' 45 | - 'performance/*' 46 | - '.github/FUNDING.YML' 47 | - '.github/workflows/ci-old.yml' 48 | - '.github/workflows/build.yml' 49 | - '.github/workflows/build*.yml' 50 | - '.github/actions/test-build/action.yml' 51 | - '.github/actions/build*/*.*' 52 | - '.github/actions/build/*.*' 53 | - '**/*.md' 54 | - '**/*.d.ts' 55 | - '**/*.bat' 56 | - '.travis.yml' 57 | - 'Dockerfile' 58 | - '.gitconfig' 59 | - '.gitignore' 60 | - 'appveyor*.*' 61 | - 'LICENSE*' 62 | - '.idea/**' 63 | - '.vscode/**' 64 | - '*.bat' 65 | - '*.nuspec' 66 | - 'tools/nuget/*' 67 | - '.npmignore' 68 | - 'test/config.json' 69 | - 'test/double' 70 | - '.circleci' 71 | - '.circleci/*' 72 | - 'README.md' 73 | - '*.sln' 74 | - '*.vcxproj' 75 | 76 | env: 77 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true # required to setup CSC 78 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 79 | DOTNET_NOLOGO: 1 80 | 81 | jobs: 82 | test: 83 | runs-on: ${{ matrix.os }} 84 | name: test-${{ matrix.os }}-node-${{ matrix.node }} 85 | strategy: 86 | fail-fast: false 87 | matrix: 88 | os: [macos-13, macos-15, ubuntu-24.04, ubuntu-24.04-arm, windows-2025, windows-11-arm] 89 | # os: [macos-15, windows-2025, windows-11-arm] 90 | # node: [18, 20, 22, 23] 91 | node: [18, 20, 22, 24] 92 | steps: 93 | 94 | - name: Checkout code 95 | uses: actions/checkout@v4 96 | 97 | - name: Skip arm64 tests 98 | if: matrix.os == 'windows-11-arm' && matrix.node < 20 99 | uses: actions/github-script@v7 100 | with: 101 | result-encoding: string 102 | script: | 103 | core.notice('Skipping arm64 tests on Windows ARM for Node.js version ' + ${{ matrix.node }}); 104 | 105 | - name: Setup env 106 | if: matrix.os != 'windows-11-arm' || matrix.node >= 20 107 | uses: ./.github/actions/setup-env 108 | with: 109 | node: ${{ matrix.node }} 110 | os: ${{ matrix.os }} 111 | 112 | - name: Run .NET 4.5 tests 113 | if: matrix.os != 'windows-11-arm' || matrix.node >= 20 114 | shell: bash 115 | run: node tools/test.js CI 116 | 117 | - name: "Run .net core tests" 118 | if: matrix.os != 'windows-11-arm' || matrix.node >= 20 119 | run: node tools/test.js CI 120 | env: 121 | EDGE_USE_CORECLR: 1 122 | 123 | - name: Test report 124 | if: matrix.os != 'windows-11-arm' || matrix.node >= 20 125 | uses: ./.github/actions/create-test-report 126 | with: 127 | node: ${{ matrix.node }} 128 | os: ${{ matrix.os }} 129 | 130 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.lock.json 10 | *.tgz 11 | 12 | publish 13 | .vscode 14 | .idea 15 | .vs 16 | 17 | pids 18 | logs 19 | results 20 | 21 | node_modules 22 | npm-debug.log 23 | /build 24 | 25 | bin/ 26 | obj/ 27 | *.user 28 | *.suo 29 | packages/* 30 | _ReSharper* 31 | src/*.sln 32 | src/EdgeJs.vcxproj 33 | 34 | Edge.Tests.* 35 | node.exe 36 | Sample105.* 37 | 38 | .DS_Store 39 | *.sublime-project 40 | *.sublime-workspace 41 | 42 | .cproject 43 | .project 44 | .metadata/ 45 | .settings/ 46 | 47 | adhoc/ 48 | 49 | *cmake* 50 | 51 | package/ 52 | tools/build 53 | 54 | /src/double/Edge.js/obj/ 55 | /src/double/Edge.js/bin/ 56 | /src/double/Edge.js.CSharp/obj/ 57 | /src/double/Edge.js.CSharp/bin/ 58 | /src/double/Edge.js/*.sln 59 | /src/double/Edge.js.CSharp/*.sln 60 | /src/Debug/ 61 | 62 | /test/obj/ 63 | /test/bin/ 64 | /test/Properties/ 65 | /test/test.nuget.cache 66 | 67 | tools/nuget/content 68 | tools/nuget/lib 69 | tools/nuget/*.nupkg 70 | tools/nuget/*.zip 71 | tools/*.nupkg 72 | tools/*.zip 73 | tools/nuget.exe 74 | 75 | *test-results*.* 76 | TemporaryGeneratedFile*.* 77 | /lib/native/win32/ia32/*/concrt140.dll 78 | /lib/native/win32/ia32/*/msvcp140.dll 79 | /lib/native/win32/ia32/*/vccorlib140.dll 80 | /lib/native/win32/ia32/*/vcruntime140.dll 81 | 82 | /lib/native/win32/x64/*/concrt140.dll 83 | /lib/native/win32/x64/*/msvcp140.dll 84 | /lib/native/win32/x64/*/vccorlib140.dll 85 | /lib/native/win32/x64/*/vcruntime140.dll 86 | 87 | /lib/native/win32/arm64/*/concrt140.dll 88 | /lib/native/win32/arm64/*/msvcp140.dll 89 | /lib/native/win32/arm64/*/vccorlib140.dll 90 | /lib/native/win32/arm64/*/vcruntime140.dll 91 | 92 | test/mochawesome-report 93 | mochawesome-report 94 | mochawesome.json 95 | 96 | release 97 | *.zip 98 | 99 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.lock.json 10 | *.tgz 11 | 12 | publish 13 | .vscode 14 | .idea 15 | .vs 16 | 17 | pids 18 | logs 19 | results 20 | 21 | node_modules 22 | npm-debug.log 23 | build 24 | 25 | bin/ 26 | obj/ 27 | *.user 28 | *.suo 29 | packages/* 30 | _ReSharper* 31 | src/*.sln 32 | src/EdgeJs.vcxproj 33 | 34 | Edge.Tests.* 35 | node.exe 36 | Sample105.* 37 | 38 | .DS_Store 39 | *.sublime-project 40 | *.sublime-workspace 41 | 42 | .cproject 43 | .project 44 | .metadata/ 45 | .settings/ 46 | 47 | adhoc/ 48 | 49 | *cmake* 50 | 51 | package/ 52 | tools/build 53 | 54 | /src/double/Edge.js/obj/ 55 | /src/double/Edge.js/bin/ 56 | /src/double/Edge.js.CSharp/obj/ 57 | /src/double/Edge.js.CSharp/bin/ 58 | /src/double/Edge.js/*.sln 59 | /src/double/Edge.js.CSharp/*.sln 60 | /src/Debug/ 61 | 62 | /test/obj/ 63 | /test/bin/ 64 | /test/Properties/ 65 | /test/test.nuget.cache 66 | 67 | tools/nuget/content 68 | tools/nuget/lib 69 | tools/nuget/*.zip 70 | tools/*.zip 71 | tools/nuget.exe 72 | 73 | test-results*.* 74 | /lib/native/win32/ia32/*/concrt140.dll 75 | /lib/native/win32/ia32/*/msvcp140.dll 76 | /lib/native/win32/ia32/*/vccorlib140.dll 77 | /lib/native/win32/ia32/*/vcruntime140.dll 78 | 79 | /lib/native/win32/x64/*/concrt140.dll 80 | /lib/native/win32/x64/*/msvcp140.dll 81 | /lib/native/win32/x64/*/vccorlib140.dll 82 | /lib/native/win32/x64/*/vcruntime140.dll 83 | 84 | /lib/native/win32/arm64/*/concrt140.dll 85 | /lib/native/win32/arm64/*/msvcp140.dll 86 | /lib/native/win32/arm64/*/vccorlib140.dll 87 | /lib/native/win32/arm64/*/vcruntime140.dll 88 | 89 | test 90 | stress 91 | samples 92 | performance 93 | *.bat 94 | tools/*.cs 95 | tools/*.vbs 96 | tools/nuget 97 | *.nupkg 98 | appveyor*.* 99 | .github 100 | tools/coverage.js 101 | tools/test*.js 102 | tools/download*.js 103 | test/mochawesome-report 104 | mochawesome-report 105 | mochawesome.json 106 | .circleci 107 | *.sln 108 | xunit*.* 109 | getVersion*.js 110 | *.vcxproj 111 | *.zip 112 | CMakeLists.txt 113 | CMake/ -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | # update apt-get 4 | RUN apt-get -y update 5 | 6 | ENV DEBIAN_FRONTEND=noninteractive 7 | 8 | RUN apt-get install -y apt-utils 9 | 10 | # install curl, sudo, wget 11 | RUN apt-get install -y curl sudo wget 12 | 13 | RUN mkdir /devvol 14 | VOLUME /devvol 15 | 16 | RUN apt-get -y update 17 | 18 | # install dependencies 19 | RUN apt-get install -y apt-transport-https build-essential libgconf-2-4 python3 git libglib2.0-dev 20 | 21 | # install node 22 | 23 | RUN curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash - 24 | RUN sudo apt-get install -y nodejs 25 | 26 | # install net core 27 | 28 | RUN wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 29 | RUN sudo dpkg -i packages-microsoft-prod.deb 30 | RUN sudo apt-get update 31 | RUN sudo apt-get install -y dotnet-sdk-8.0 32 | 33 | RUN npm i -g node-gyp -------------------------------------------------------------------------------- /EdgeJs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Edge.js", "src\double\Edge.js\Edge.js.csproj", "{D232E683-ED16-4B7B-BD76-44A9DE96F79E}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{E94194B3-965D-4CC5-8080-C897A9B607E9}" 6 | EndProject 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bootstrap", "lib\bootstrap\bootstrap.csproj", "{9AF3DB99-E51A-463F-896A-A9F6123C6999}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {D232E683-ED16-4B7B-BD76-44A9DE96F79E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {D232E683-ED16-4B7B-BD76-44A9DE96F79E}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {D232E683-ED16-4B7B-BD76-44A9DE96F79E}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {D232E683-ED16-4B7B-BD76-44A9DE96F79E}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {E94194B3-965D-4CC5-8080-C897A9B607E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {E94194B3-965D-4CC5-8080-C897A9B607E9}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {E94194B3-965D-4CC5-8080-C897A9B607E9}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {E94194B3-965D-4CC5-8080-C897A9B607E9}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {9AF3DB99-E51A-463F-896A-A9F6123C6999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {9AF3DB99-E51A-463F-896A-A9F6123C6999}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {9AF3DB99-E51A-463F-896A-A9F6123C6999}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {9AF3DB99-E51A-463F-896A-A9F6123C6999}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2024 Tomasz Janczuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /appveyor.ps1: -------------------------------------------------------------------------------- 1 | 2 | #------------------------------- 3 | # Installation 4 | #------------------------------- 5 | 6 | function Get-TimeStamp { 7 | return "[{0:yyyy/MM/dd} {0:HH:mm:ss}]" -f (Get-Date) 8 | } 9 | 10 | Write-Host "$(Get-TimeStamp) Downloading latest .NET Core SDK..." 11 | 12 | (New-Object System.Net.WebClient).DownloadFile('https://download.visualstudio.microsoft.com/download/pr/9e753d68-7701-4ddf-b358-79d64e776945/2a58564c6d0779a7b443a692c520782f/dotnet-sdk-8.0.203-win-x64.exe','C:\projects\edge-js\dotnet-core-sdk.exe') 13 | 14 | Write-Host "$(Get-TimeStamp) Installing .NET Core SDK..." 15 | 16 | Start-Process -Wait 'C:\projects\edge-js\dotnet-core-sdk.exe' -ArgumentList '/install /quiet /norestart'; 17 | 18 | # Invoke-Command -ScriptBlock { dotnet-core-sdk.exe /install /quiet /norestart } 19 | 20 | Write-Host "$(Get-TimeStamp) Installation succeeded." -ForegroundColor Green 21 | -------------------------------------------------------------------------------- /appveyor_disable.yml: -------------------------------------------------------------------------------- 1 | branches: 2 | except: 3 | - circleci 4 | 5 | image: 6 | # - Visual Studio 2022 7 | # - Ubuntu2204 8 | - macos-ventura 9 | - macos-sonoma 10 | 11 | environment: 12 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 13 | matrix: 14 | # node.js 15 | # - nodejs: "23" 16 | # - nodejs: "22" 17 | - nodejs: "20" 18 | # - nodejs: "18" 19 | 20 | install: 21 | # - sh: if [ "$APPVEYOR_BUILD_WORKER_IMAGE" = 'Ubuntu2204' ]; then sudo apt-get -qq update && sudo apt-get -y -qq install build-essential libgconf-2-4 python3 libglib2.0-dev; fi 22 | # - cmd: powershell .\appveyor.ps1 23 | - cmd: powershell Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs) x64 24 | - sh: brew update 25 | - sh: brew upgrade 26 | - sh: brew install mono --overwrite 27 | - sh: brew reinstall pkg-config 28 | - sh: nvm ls 29 | - sh: nvm use $nodejs || nvm install $nodejs 30 | - cmd: node -v && npm -v && dotnet --version 31 | - sh: node -v && npm -v && dotnet --version 32 | - npm install --no-audit 33 | 34 | test_script: 35 | - cmd: node tools/test.js CI 36 | - cmd: SET EDGE_USE_CORECLR=1 & node tools/test.js CI 37 | - sh: node tools/test.js CI 38 | - sh: EDGE_USE_CORECLR=1 node tools/test.js CI 39 | 40 | after_test: 41 | - ps: | 42 | $url = "https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)" 43 | $file = '.\test-results.xml' 44 | (New-Object 'System.Net.WebClient').UploadFile($url, (Resolve-Path '.\test-results.xml')) 45 | Push-AppveyorArtifact (Resolve-Path '.\test-results.xml') 46 | Push-AppveyorArtifact (Resolve-Path '.\mochawesome.json') 47 | 48 | skip_commits: 49 | files: 50 | - samples/* 51 | - stress/* 52 | - performance/* 53 | - '.github' 54 | - '.github/*' 55 | - '.github/**/*' 56 | - '.github/**/**/*' 57 | - '**/*.md' 58 | - '**/*.d.ts' 59 | - '**/*.bat' 60 | - '.travis.yml' 61 | - 'Dockerfile' 62 | - 'README.md' 63 | - 'LICENSE*' 64 | - '.idea/**' 65 | - '.vscode/**' 66 | - '.gitignore' 67 | - '*.bat' 68 | - '*.nuspec' 69 | - 'tools/nuget/*' 70 | - '.npmignore' 71 | - 'test/config.json' 72 | - 'test/double' 73 | - 'appveyor_double.yml' 74 | - '.circleci' 75 | - '.circleci/*' 76 | - '*.sln' 77 | - '*.vcxproj' 78 | 79 | 80 | build: off 81 | 82 | cache: 83 | - node_modules -> package-lock.json -------------------------------------------------------------------------------- /appveyor_double.yml: -------------------------------------------------------------------------------- 1 | image: 2 | - Visual Studio 2019 3 | 4 | environment: 5 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 6 | 7 | build_script: 8 | - dotnet restore test/double/double_test/double_test.sln 9 | - dotnet build test/double/double_test/double_test.sln --configuration Release 10 | 11 | test_script: 12 | - nunit3-console test/double/double_test/bin/Release/net462/double_test.dll --result=test-results.xml;format=AppVeyor 13 | 14 | after_test: 15 | - ps: | 16 | Push-AppveyorArtifact (Resolve-Path '.\test-results.xml') 17 | 18 | only_commits: 19 | files: 20 | - 'test/double/**' 21 | - 'test/double/double_test/*' 22 | - 'test/double/double_test/**/*' 23 | - 'appveyor_double.yml' 24 | - 'src/double/Edge.js/dotnet/EdgeJs.cs' 25 | -------------------------------------------------------------------------------- /edge-js.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'edge-js' { 2 | function func(params: string | Function | Params | Source | TSQL): Func 3 | function func(language: string, params: string | Function | Params | Source | TSQL): Func 4 | interface Params { 5 | assemblyFile: string 6 | typeName?: string 7 | methodName?: string 8 | } 9 | 10 | interface Source { 11 | source: string | Function 12 | references?: string[] 13 | } 14 | 15 | interface TSQL { 16 | source: string 17 | connectionString?: string 18 | commandTimeout?: number 19 | } 20 | 21 | interface Func { 22 | (payload: TInput, callback: (error: Error, result: TOutput) => void): void; 23 | (payload: TInput, sync: true): TOutput; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/bootstrap/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ -------------------------------------------------------------------------------- /lib/bootstrap/Dummy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public class Dummy 4 | { 5 | } -------------------------------------------------------------------------------- /lib/bootstrap/bootstrap.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | true 6 | bootstrap 7 | bootstrap 8 | default 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/double_edge.js: -------------------------------------------------------------------------------- 1 | // Fix #176 for GUI applications on Windows 2 | try { 3 | var stdout = process.stdout; 4 | } 5 | catch (e) { 6 | // This is a Windows GUI application without stdout and stderr defined. 7 | // Define process.stdout and process.stderr so that all output is discarded. 8 | (function () { 9 | var stream = require('stream'); 10 | var NullStream = function (o) { 11 | stream.Writable.call(this); 12 | this._write = function (c, e, cb) { cb && cb(); }; 13 | } 14 | require('util').inherits(NullStream, stream.Writable); 15 | var nullStream = new NullStream(); 16 | process.__defineGetter__('stdout', function () { return nullStream; }); 17 | process.__defineGetter__('stderr', function () { return nullStream; }); 18 | })(); 19 | } 20 | 21 | process.env['EDGE_NATIVE'] = process.env['EDGE_NATIVE'] || 22 | __dirname + (process.arch === 'x64' ? '\\x64\\edge_nativeclr.node' : '\\x86\\edge_nativeclr.node'); 23 | 24 | var edge = require('./edge.js'); 25 | 26 | 27 | var assemblyFile = __dirname + '\\..\\EdgeJs.dll'; 28 | const edgeSwitch = "-EdgeJs:"; 29 | process.argv.forEach(e => { 30 | if(e.startsWith(edgeSwitch)) { 31 | const path = e.substring(edgeSwitch.length); 32 | assemblyFile = path; 33 | } 34 | }) 35 | 36 | var intervalID; 37 | 38 | var initialize = edge.func({ 39 | assemblyFile, 40 | typeName: 'EdgeJs.Edge', 41 | methodName: 'InitializeInternal' 42 | }); 43 | 44 | var compileFunc = function (data, callback) { 45 | if (data === "ABORT") { 46 | clearInterval(intervalID); 47 | callback(null, true); 48 | } else { 49 | var wrapper = '(function () { ' + data + ' })'; 50 | var funcFactory = eval(wrapper); 51 | var func = funcFactory(); 52 | if (typeof func !== 'function') { 53 | throw new Error('Node.js code must return an instance of a JavaScript function. ' 54 | + 'Please use `return` statement to return a function.'); 55 | } 56 | callback(null, func); 57 | } 58 | }; 59 | 60 | initialize(compileFunc, function (error, data) { 61 | if (error) throw error; 62 | }); 63 | 64 | // prevent the V8 thread from exiting for the lifetime of the CLR application 65 | intervalID = setInterval(function () { }, 3600000); -------------------------------------------------------------------------------- /lib/native/darwin/arm64/18/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/18/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/arm64/18/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/18/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/18/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/18/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/18/node.version: -------------------------------------------------------------------------------- 1 | 18.20.8 -------------------------------------------------------------------------------- /lib/native/darwin/arm64/20/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/20/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/arm64/20/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/20/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/20/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/20/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/20/node.version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /lib/native/darwin/arm64/22/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/22/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/arm64/22/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/22/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/22/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/22/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/22/node.version: -------------------------------------------------------------------------------- 1 | 22.16.0 -------------------------------------------------------------------------------- /lib/native/darwin/arm64/24/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/24/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/arm64/24/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/24/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/24/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/arm64/24/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/arm64/24/node.version: -------------------------------------------------------------------------------- 1 | 24.1.0 -------------------------------------------------------------------------------- /lib/native/darwin/x64/18/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/18/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/x64/18/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/18/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/18/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/18/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/18/node.version: -------------------------------------------------------------------------------- 1 | 18.20.8 -------------------------------------------------------------------------------- /lib/native/darwin/x64/20/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/20/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/x64/20/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/20/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/20/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/20/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/20/node.version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /lib/native/darwin/x64/22/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/22/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/x64/22/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/22/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/22/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/22/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/22/node.version: -------------------------------------------------------------------------------- 1 | 22.16.0 -------------------------------------------------------------------------------- /lib/native/darwin/x64/24/MonoEmbedding.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/24/MonoEmbedding.exe -------------------------------------------------------------------------------- /lib/native/darwin/x64/24/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/24/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/24/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/darwin/x64/24/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/darwin/x64/24/node.version: -------------------------------------------------------------------------------- 1 | 24.1.0 -------------------------------------------------------------------------------- /lib/native/win32/arm64/20/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/20/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/20/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/20/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/20/node.version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /lib/native/win32/arm64/22/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/22/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/22/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/22/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/22/node.version: -------------------------------------------------------------------------------- 1 | 22.16.0 -------------------------------------------------------------------------------- /lib/native/win32/arm64/24/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/24/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/24/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/24/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/arm64/24/node.version: -------------------------------------------------------------------------------- 1 | 24.1.0 -------------------------------------------------------------------------------- /lib/native/win32/arm64/concrt140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/concrt140.dll -------------------------------------------------------------------------------- /lib/native/win32/arm64/msvcp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/msvcp140.dll -------------------------------------------------------------------------------- /lib/native/win32/arm64/vccorlib140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/vccorlib140.dll -------------------------------------------------------------------------------- /lib/native/win32/arm64/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/arm64/vcruntime140.dll -------------------------------------------------------------------------------- /lib/native/win32/ia32/18/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/18/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/18/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/18/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/18/node.version: -------------------------------------------------------------------------------- 1 | 18.20.8 -------------------------------------------------------------------------------- /lib/native/win32/ia32/20/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/20/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/20/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/20/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/20/node.version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /lib/native/win32/ia32/22/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/22/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/22/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/22/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/ia32/22/node.version: -------------------------------------------------------------------------------- 1 | 22.16.0 -------------------------------------------------------------------------------- /lib/native/win32/ia32/concrt140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/concrt140.dll -------------------------------------------------------------------------------- /lib/native/win32/ia32/msvcp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/msvcp140.dll -------------------------------------------------------------------------------- /lib/native/win32/ia32/vccorlib140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/vccorlib140.dll -------------------------------------------------------------------------------- /lib/native/win32/ia32/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/ia32/vcruntime140.dll -------------------------------------------------------------------------------- /lib/native/win32/x64/18/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/18/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/18/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/18/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/18/node.version: -------------------------------------------------------------------------------- 1 | 18.20.8 -------------------------------------------------------------------------------- /lib/native/win32/x64/20/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/20/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/20/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/20/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/20/node.version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /lib/native/win32/x64/22/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/22/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/22/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/22/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/22/node.version: -------------------------------------------------------------------------------- 1 | 22.16.0 -------------------------------------------------------------------------------- /lib/native/win32/x64/24/edge_coreclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/24/edge_coreclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/24/edge_nativeclr.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/24/edge_nativeclr.node -------------------------------------------------------------------------------- /lib/native/win32/x64/24/node.version: -------------------------------------------------------------------------------- 1 | 24.1.0 -------------------------------------------------------------------------------- /lib/native/win32/x64/concrt140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/concrt140.dll -------------------------------------------------------------------------------- /lib/native/win32/x64/msvcp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/msvcp140.dll -------------------------------------------------------------------------------- /lib/native/win32/x64/vccorlib140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/vccorlib140.dll -------------------------------------------------------------------------------- /lib/native/win32/x64/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/lib/native/win32/x64/vcruntime140.dll -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edge-js", 3 | "author": { 4 | "name": "Tomasz Janczuk ", 5 | "url": "http://tomasz.janczuk.org", 6 | "twitter": "tjanczuk" 7 | }, 8 | "version": "24.0.4", 9 | "description": "Edge.js: run .NET and Node.js in-process on Windows, Mac OS, and Linux", 10 | "tags": [ 11 | "owin", 12 | "edge", 13 | "net", 14 | "clr", 15 | "coreclr", 16 | "c#", 17 | "mono", 18 | "managed", 19 | ".net", 20 | "edge-js" 21 | ], 22 | "keywords": [ 23 | "owin", 24 | "edge", 25 | "net", 26 | "clr", 27 | "coreclr", 28 | "c#", 29 | "mono", 30 | "managed", 31 | ".net", 32 | "edge-js" 33 | ], 34 | "main": "./lib/edge.js", 35 | "types": "edge-js.d.ts", 36 | "engines": { 37 | "npm": ">=8.0.0", 38 | "node": ">=16.0.0" 39 | }, 40 | "license": "MIT", 41 | "dependencies": { 42 | "edge-cs": "npm:@agracio/edge-cs@^1.3.7", 43 | "nan": "^2.22.2" 44 | }, 45 | "devDependencies": { 46 | "follow-redirects": "^1.15.9", 47 | "junit-report-merger": "7.0.1", 48 | "mocha": "11.5.0", 49 | "mocha-junit-reporter": "^2.2.1", 50 | "mocha-multi-reporters": "^1.5.1", 51 | "mochawesome": "^7.1.3", 52 | "mochawesome-merge": "^5.0.0", 53 | "mochawesome-report-generator": "^6.2.0" 54 | }, 55 | "homepage": "https://github.com/agracio/edge-js", 56 | "repository": { 57 | "type": "git", 58 | "url": "git+ssh://git@github.com/agracio/edge-js.git" 59 | }, 60 | "bugs": { 61 | "url": "http://github.com/agracio/edge-js/issues" 62 | }, 63 | "scripts": { 64 | "install": "node tools/install.js", 65 | "test": "node tools/test.js" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /performance/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | BookService/packages/ -------------------------------------------------------------------------------- /performance/BookService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /performance/BookService/BookService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {860AE049-3944-4CAB-A087-1CDEAEEFCC14} 8 | Exe 9 | Properties 10 | BookService 11 | BookService 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /performance/BookService/BookService.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookService", "BookService.csproj", "{860AE049-3944-4CAB-A087-1CDEAEEFCC14}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {860AE049-3944-4CAB-A087-1CDEAEEFCC14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {860AE049-3944-4CAB-A087-1CDEAEEFCC14}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {860AE049-3944-4CAB-A087-1CDEAEEFCC14}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {860AE049-3944-4CAB-A087-1CDEAEEFCC14}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /performance/BookService/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Net.Http.Headers; 4 | using System.ServiceModel; 5 | using System.Web.Http; 6 | using System.Web.Http.SelfHost; 7 | 8 | namespace BookService 9 | { 10 | public class Book 11 | { 12 | public string title = "Run .NET and node.js in-process with edge.js"; 13 | public object author = new { first = "Tomasz", last = "Janczuk" }; 14 | public int year = 2013; 15 | public double price = 24.99; 16 | public bool available = true; 17 | public string description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus posuere tincidunt felis, et mattis mauris ultrices quis. Cras molestie, quam varius tincidunt tincidunt, mi magna imperdiet lacus, quis elementum ante nibh quis orci. In posuere erat sed tellus lacinia luctus. Praesent sodales tellus mauris, et egestas justo. In blandit, metus non congue adipiscing, est orci luctus odio, non sagittis erat orci ac sapien. Proin ut est id enim mattis volutpat. Vivamus ultrices dapibus feugiat. In dictum tincidunt eros, non pretium nisi rhoncus in. Duis a lacus et elit feugiat ullamcorper. Mauris tempor turpis nulla. Nullam nec facilisis elit."; 18 | public byte[] picture = new byte[16000]; 19 | public object[] tags = new object[] { ".NET", "node.js", "CLR", "V8", "interop" }; 20 | } 21 | 22 | public class BookController : ApiController 23 | { 24 | static readonly Uri baseAddress = new Uri("http://localhost:31415/"); 25 | 26 | public Book Get() 27 | { 28 | return new Book(); 29 | } 30 | 31 | static void Main(string[] args) 32 | { 33 | HttpSelfHostServer server = null; 34 | try 35 | { 36 | HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(baseAddress); 37 | config.HostNameComparisonMode = HostNameComparisonMode.Exact; 38 | 39 | // Register default route 40 | config.Routes.MapHttpRoute( 41 | name: "DefaultApi", 42 | routeTemplate: "api/{controller}" 43 | ); 44 | 45 | server = new HttpSelfHostServer(config); 46 | server.OpenAsync().Wait(); 47 | Console.WriteLine("Listening on " + baseAddress); 48 | Console.WriteLine("Hit ENTER to exit..."); 49 | Console.ReadLine(); 50 | } 51 | catch (Exception e) 52 | { 53 | Console.WriteLine("Could not start server: {0}", e.GetBaseException().Message); 54 | Console.WriteLine("Hit ENTER to exit..."); 55 | Console.ReadLine(); 56 | } 57 | finally 58 | { 59 | if (server != null) 60 | { 61 | server.CloseAsync().Wait(); 62 | } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /performance/BookService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BookService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BookService")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("00b715fc-f588-4964-8edc-6d9665df29b6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /performance/BookService/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mcs -sdk:4.5 Program.cs /r:System.Net.Http.dll /r:System.ServiceModel.dll /r:System.Web.Http.dll /r:System.Web.Http.SelfHost.dll 3 | -------------------------------------------------------------------------------- /performance/BookService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /performance/latency.js: -------------------------------------------------------------------------------- 1 | function help() { 2 | console.log('Usage: node latency.js i|x '); 3 | console.log(' i - 1 compilation, in-process loop of N calls'); 4 | console.log(' c - in-process loop of N compilations and calls'); 5 | console.log(' x - child process loop of N iterations'); 6 | console.log('e.g. node latency.js i 1000'); 7 | process.exit(1); 8 | } 9 | 10 | if (process.argv.length !== 4) 11 | help(); 12 | 13 | if (isNaN(process.argv[3])) 14 | help(); 15 | 16 | var N = +process.argv[3]; 17 | 18 | if (N < 1) 19 | help(); 20 | 21 | if (process.argv[2] === 'i') { 22 | var func = require('../lib/edge').func(function () {/* 23 | async (input) => { 24 | return ".NET welcomes " + input.ToString(); 25 | } 26 | */}); 27 | var M = N; 28 | var start = Date.now(); 29 | one_i(); 30 | function one_i() { 31 | func('Node.js', function (error, result) { 32 | if (error) throw error; 33 | if (--M <= 0) { 34 | var delta = Date.now() - start; 35 | console.log(delta, delta / N); 36 | } 37 | else 38 | setImmediate(one_i); 39 | }); 40 | } 41 | }else if (process.argv[2] === 'c') { 42 | var csharp = 'async (input) => { return ".NET welcomes " + input.ToString(); } /*'; 43 | 44 | var edge = require('../lib/edge'); 45 | var M = N; 46 | var start = Date.now(); 47 | one_c(); 48 | function one_c() { 49 | var code = csharp + M + '*/'; // force cache miss and recompile 50 | var func = edge.func(code); 51 | func('Node.js', function (error, result) { 52 | if (error) throw error; 53 | if (--M <= 0) { 54 | var delta = Date.now() - start; 55 | console.log(delta, delta / N); 56 | } 57 | else 58 | setImmediate(one_c); 59 | }); 60 | } 61 | } 62 | else if (process.argv[2] === 'x') { 63 | var child_process = require('child_process'); 64 | var cmd = [process.argv[0], process.argv[1], 'i', '1'].join(' '); 65 | var M = N; 66 | var start = Date.now(); 67 | one_x(); 68 | function one_x() { 69 | child_process.exec(cmd, function (error) { 70 | if (error) throw error; 71 | if (--M <= 0) { 72 | var delta = Date.now() - start; 73 | console.log(delta, delta / N); 74 | } 75 | else 76 | setImmediate(one_x); 77 | }); 78 | } 79 | } 80 | else 81 | help(); 82 | -------------------------------------------------------------------------------- /performance/marshal_clr2v8.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | var callCount = process.env.EDGE_CALL_COUNT || 10000; 4 | var edgePerformanceDll = path.join(__dirname, 'Edge.Performance.dll'); 5 | 6 | var measure = function (func) { 7 | var start = Date.now(); 8 | var i = 0; 9 | 10 | function one() { 11 | func({ 12 | title: 'Run .NET and node.js in-process with edge.js', 13 | author: { 14 | first: 'Tomasz', 15 | last: 'Janczuk' 16 | }, 17 | year: 2013, 18 | price: 24.99, 19 | available: true, 20 | description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus posuere tincidunt felis, et mattis mauris ultrices quis. Cras molestie, quam varius tincidunt tincidunt, mi magna imperdiet lacus, quis elementum ante nibh quis orci. In posuere erat sed tellus lacinia luctus. Praesent sodales tellus mauris, et egestas justo. In blandit, metus non congue adipiscing, est orci luctus odio, non sagittis erat orci ac sapien. Proin ut est id enim mattis volutpat. Vivamus ultrices dapibus feugiat. In dictum tincidunt eros, non pretium nisi rhoncus in. Duis a lacus et elit feugiat ullamcorper. Mauris tempor turpis nulla. Nullam nec facilisis elit.', 21 | picture: new Buffer(16000), 22 | tags: [ '.NET', 'node.js', 'CLR', 'V8', 'interop'] 23 | }, function (error, callbck) { 24 | if (error) throw error; 25 | if (++i < callCount) setImmediate(one); 26 | else finish(); 27 | }); 28 | } 29 | 30 | function finish() { 31 | var delta = Date.now() - start; 32 | var result = process.memoryUsage(); 33 | result.latency = delta / callCount; 34 | console.log(result); 35 | } 36 | 37 | one(); 38 | }; 39 | 40 | var baseline = function () { 41 | measure(function (input, callback) { 42 | var book = { 43 | title: 'Run .NET and node.js in-process with edge.js', 44 | author: { 45 | first: 'Tomasz', 46 | last: 'Janczuk' 47 | }, 48 | year: 2013, 49 | price: 24.99, 50 | available: true, 51 | description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus posuere tincidunt felis, et mattis mauris ultrices quis. Cras molestie, quam varius tincidunt tincidunt, mi magna imperdiet lacus, quis elementum ante nibh quis orci. In posuere erat sed tellus lacinia luctus. Praesent sodales tellus mauris, et egestas justo. In blandit, metus non congue adipiscing, est orci luctus odio, non sagittis erat orci ac sapien. Proin ut est id enim mattis volutpat. Vivamus ultrices dapibus feugiat. In dictum tincidunt eros, non pretium nisi rhoncus in. Duis a lacus et elit feugiat ullamcorper. Mauris tempor turpis nulla. Nullam nec facilisis elit.', 52 | picture: new Buffer(16000), 53 | tags: [ '.NET', 'node.js', 'CLR', 'V8', 'interop'] 54 | } 55 | callback(null, book); 56 | }); 57 | }; 58 | 59 | var clr2v8 = function () { 60 | measure(require('../lib/edge').func({ 61 | assemblyFile: edgePerformanceDll, 62 | methodName: 'Invoke' 63 | })); 64 | }; 65 | 66 | var crossProcess = function () { 67 | var http = require('http'); 68 | measure(function (input, callback) { 69 | http.get("http://localhost:31415/api/book", function(res) { 70 | if (res.statusCode !== 200) { 71 | return callback(new Error('Status code: ' + res.statusCode)); 72 | } 73 | 74 | var body = ''; 75 | res.on('data', function (chunk) { body += chunk; }); 76 | res.on('end', function () { 77 | callback(null, JSON.parse(body)); 78 | }) 79 | }).on('error', callback); 80 | }); 81 | }; 82 | 83 | var cases = { 84 | js: baseline, 85 | edge: clr2v8, 86 | xproc: crossProcess 87 | }; 88 | 89 | if (!cases[process.argv[2]]) { 90 | console.log('Usage: marshal_clr2v8.js ' + Object.getOwnPropertyNames(cases).join('|')); 91 | process.exit(1); 92 | } 93 | else { 94 | cases[process.argv[2]](); 95 | } 96 | -------------------------------------------------------------------------------- /performance/performance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | #pragma warning disable 1998 8 | 9 | namespace Edge.Performance 10 | { 11 | public class Startup 12 | { 13 | public async Task Invoke(dynamic input) 14 | { 15 | var book = new 16 | { 17 | title = "Run .NET and node.js in-process with edge.js", 18 | author = new { 19 | first = "Tomasz", 20 | last = "Janczuk" 21 | }, 22 | year = 2013, 23 | price = 24.99, 24 | available = true, 25 | description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus posuere tincidunt felis, et mattis mauris ultrices quis. Cras molestie, quam varius tincidunt tincidunt, mi magna imperdiet lacus, quis elementum ante nibh quis orci. In posuere erat sed tellus lacinia luctus. Praesent sodales tellus mauris, et egestas justo. In blandit, metus non congue adipiscing, est orci luctus odio, non sagittis erat orci ac sapien. Proin ut est id enim mattis volutpat. Vivamus ultrices dapibus feugiat. In dictum tincidunt eros, non pretium nisi rhoncus in. Duis a lacus et elit feugiat ullamcorper. Mauris tempor turpis nulla. Nullam nec facilisis elit.", 26 | picture = new byte[16000], 27 | tags = new object[] { ".NET", "node.js", "CLR", "V8", "interop" } 28 | }; 29 | 30 | return book; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /samples/101_hello_lambda.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func('async (input) => { return ".NET welcomes " + input.ToString(); }'); 6 | 7 | hello('Node.js', function (error, result) { 8 | if (error) throw error; 9 | console.log(result); 10 | }); -------------------------------------------------------------------------------- /samples/102_hello_function.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func(function () {/* 6 | async (input) => 7 | { 8 | return ".NET welcomes " + input.ToString(); 9 | } 10 | */}); 11 | 12 | hello('Node.js', function (error, result) { 13 | if (error) throw error; 14 | console.log(result); 15 | }); -------------------------------------------------------------------------------- /samples/103_hello_file.csx: -------------------------------------------------------------------------------- 1 | async (input) => 2 | { 3 | return ".NET welcomes " + input.ToString(); 4 | } -------------------------------------------------------------------------------- /samples/103_hello_file.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func('103_hello_file.csx'); 6 | 7 | hello('Node.js', function (error, result) { 8 | if (error) throw error; 9 | console.log(result); 10 | }); -------------------------------------------------------------------------------- /samples/104_add7_class.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var add7 = edge.func(function () {/* 6 | using System.Threading.Tasks; 7 | 8 | public class Startup 9 | { 10 | public async Task Invoke(object input) 11 | { 12 | return this.Add7((int)input); 13 | } 14 | 15 | int Add7(int v) 16 | { 17 | return Helper.Add7(v); 18 | } 19 | } 20 | 21 | static class Helper 22 | { 23 | public static int Add7(int v) 24 | { 25 | return v + 7; 26 | } 27 | } 28 | */}); 29 | 30 | add7(12, function (error, result) { 31 | if (error) throw error; 32 | console.log(result); 33 | }); -------------------------------------------------------------------------------- /samples/105_add7_dll.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | // Compile Sample105.dll with 4 | // - on Windows (.NET Framework): 5 | // csc.exe /target:library /debug Sample105.cs 6 | // - on MacOS/Linux (Mono): 7 | // mcs -sdk:4.5 Sample105.cs -target:library 8 | 9 | var edge = require('../lib/edge'); 10 | 11 | var add7 = edge.func('Sample105.dll'); 12 | 13 | add7(12, function (error, result) { 14 | if (error) throw error; 15 | console.log(result); 16 | }); -------------------------------------------------------------------------------- /samples/106_marshal_v82clr.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func(function () {/* 6 | using System.Collections.Generic; 7 | 8 | async (data) => 9 | { 10 | Console.WriteLine("-----> In .NET:"); 11 | foreach (var kv in (IDictionary)data) 12 | { 13 | Console.WriteLine(kv.Key + ": " + kv.Value.GetType()); 14 | } 15 | 16 | return null; 17 | } 18 | */}); 19 | 20 | var payload = { 21 | anInteger: 1, 22 | aNumber: 3.1415, 23 | aString: 'foobar', 24 | aBool: true, 25 | anObject: {}, 26 | anArray: [ 'a', 1, true ], 27 | aBuffer: new Buffer(1024) 28 | } 29 | 30 | console.log('-----> In node.js:'); 31 | console.log(payload); 32 | 33 | hello(payload, function (error, result) { 34 | if (error) throw error; 35 | }); 36 | -------------------------------------------------------------------------------- /samples/107_marshal_clr2v8.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func(function () {/* 6 | async (input) => 7 | { 8 | var result = new { 9 | anInteger = 1, 10 | aNumber = 3.1415, 11 | aString = "foobar", 12 | aBool = true, 13 | anObject = new { a = "b", c = 12 }, 14 | anArray = new object[] { "a", 1, true }, 15 | aBuffer = new byte[1024] 16 | }; 17 | 18 | return result; 19 | } 20 | */}); 21 | 22 | hello(null, function (error, result) { 23 | if (error) throw error; 24 | console.log('-----> In node.js:'); 25 | console.log(result); 26 | }); 27 | -------------------------------------------------------------------------------- /samples/108_func.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var addAndMultiplyBy2 = edge.func(function () {/* 6 | using System.Collections.Generic; 7 | 8 | async (dynamic data) => 9 | { 10 | int sum = (int)data.a + (int)data.b; 11 | var multiplyBy2 = (Func>)data.multiplyBy2; 12 | return await multiplyBy2(sum); 13 | } 14 | */}); 15 | 16 | var payload = { 17 | a: 2, 18 | b: 3, 19 | multiplyBy2: function(input, callback) { 20 | callback(null, input * 2); 21 | } 22 | }; 23 | 24 | addAndMultiplyBy2(payload, function (error, result) { 25 | if (error) throw error; 26 | console.log(result); 27 | }); 28 | -------------------------------------------------------------------------------- /samples/108_lambda.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var createCounter = edge.func(function () {/* 6 | async (start) => 7 | { 8 | var k = (int)start; 9 | return (Func>)( 10 | async (i) => 11 | { 12 | return k++; 13 | } 14 | ); 15 | } 16 | */}); 17 | 18 | var nextNumber = createCounter(12, true); 19 | console.log(nextNumber(null, true)); 20 | console.log(nextNumber(null, true)); 21 | console.log(nextNumber(null, true)); 22 | -------------------------------------------------------------------------------- /samples/109_sync.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func('async (input) => { return ".NET welcomes " + input.ToString(); }'); 6 | 7 | // call the function synchronously 8 | var result = hello('Node.js', true); 9 | console.log(result); 10 | 11 | // call the same function asynchronously 12 | hello('JavaScript', function (error, result) { 13 | if (error) throw error; 14 | console.log(result); 15 | }); 16 | -------------------------------------------------------------------------------- /samples/110_clr_instance.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var createPerson = edge.func(function () {/* 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | public class Startup 10 | { 11 | public async Task Invoke(int startingSalary) 12 | { 13 | var person = new Person(startingSalary); 14 | return new { 15 | getSalary = (Func>)( 16 | async (i) => 17 | { 18 | return person.Salary; 19 | } 20 | ), 21 | giveRaise = (Func>)( 22 | async (amount) => 23 | { 24 | person.GiveRaise((int)amount); 25 | return person.Salary; 26 | } 27 | ) 28 | }; 29 | } 30 | } 31 | 32 | public class Person 33 | { 34 | public int Salary { get; private set; } 35 | 36 | public Person(int startingSalary) 37 | { 38 | this.Salary = startingSalary; 39 | } 40 | 41 | public void GiveRaise(int amount) 42 | { 43 | this.Salary += amount; 44 | } 45 | } 46 | */}); 47 | 48 | var person = createPerson(120, true); 49 | console.log(person.getSalary(null, true)); 50 | console.log(person.giveRaise(20, true)); 51 | console.log(person.getSalary(null, true)); 52 | -------------------------------------------------------------------------------- /samples/111_clr_listener.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var createController = edge.func(function () {/* 6 | using System; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | public class Startup 11 | { 12 | static TaskCompletionSource tcs; 13 | 14 | public async Task Invoke(object input) 15 | { 16 | return new { 17 | yieldControl = (Func>)((i) => { 18 | return Startup.AcquireControl(); 19 | }), 20 | regainControl = (Func>)(async (i) => { 21 | Startup.ReleaseControl(); 22 | return null; 23 | }) 24 | }; 25 | } 26 | 27 | static Task AcquireControl() 28 | { 29 | // single threaded; always called on V8 thread 30 | 31 | if (tcs != null) 32 | { 33 | throw new InvalidOperationException("CLR already controls the lifetime of the process."); 34 | } 35 | 36 | TaskCompletionSource tmp = new TaskCompletionSource(); 37 | tcs = tmp; 38 | return tmp.Task; 39 | } 40 | 41 | public static void ReleaseControl() 42 | { 43 | // multi-threaded; can be called from V8 or one of many CLR threads 44 | 45 | TaskCompletionSource tmp = Interlocked.Exchange(ref tcs, null); 46 | if (tmp != null) 47 | { 48 | tmp.SetResult(null); 49 | } 50 | } 51 | } 52 | */}); 53 | 54 | // yield control over process lifetime to CLR 55 | var controller = createController(null, true); 56 | controller.yieldControl(); 57 | console.log('Control over process lifetime yielded to CLR, the process will not exit...'); 58 | 59 | // at this point, the process will not exit until one of the following happens: 60 | // - node.js calls controller.regainControl(), or 61 | // - CLR calls Startup.ReleaseControl() 62 | 63 | // controller.regainControl(); -------------------------------------------------------------------------------- /samples/201_worker.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var hello = edge.func(function () {/* 6 | async (input) => 7 | { 8 | // we are on V8 thread here 9 | 10 | return await Task.Run(async () => { 11 | 12 | // we are on CLR thread pool thread here 13 | 14 | // simulate long running operation 15 | await Task.Delay(5000); 16 | 17 | return ".NET welcomes " + input.ToString(); 18 | }); 19 | } 20 | */}); 21 | 22 | console.log('Starting CPU bound operation...'); 23 | hello('Node.js', function (error, result) { 24 | if (error) throw error; 25 | console.log(result); 26 | }); 27 | 28 | setInterval(function() { 29 | console.log('Node.js event loop is alive'); 30 | }, 1000); 31 | -------------------------------------------------------------------------------- /samples/202_sql.csx: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | //#r "System.dll" 4 | //#r "System.Data.dll" 5 | //#r "System.Web.Extensions.dll" 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Data; 10 | using System.Data.SqlClient; 11 | using System.IO; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | using System.Web.Script.Serialization; 15 | 16 | public class Startup 17 | { 18 | public async Task Invoke(string command) 19 | { 20 | string connectionString = Environment.GetEnvironmentVariable("OWIN_SQL_CONNECTION_STRING"); 21 | 22 | if (command.StartsWith("select ", StringComparison.InvariantCultureIgnoreCase)) 23 | { 24 | return await this.ExecuteQuery(connectionString, command); 25 | } 26 | else if (command.StartsWith("insert ", StringComparison.InvariantCultureIgnoreCase) 27 | || command.StartsWith("update ", StringComparison.InvariantCultureIgnoreCase) 28 | || command.StartsWith("delete ", StringComparison.InvariantCultureIgnoreCase)) 29 | { 30 | return await this.ExecuteNonQuery(connectionString, command); 31 | } 32 | else 33 | { 34 | throw new InvalidOperationException("Unsupported type of SQL command. Only select, insert, update, and delete are supported."); 35 | } 36 | } 37 | 38 | async Task ExecuteQuery(string connectionString, string commandString) 39 | { 40 | List rows = new List(); 41 | 42 | using (SqlConnection connection = new SqlConnection(connectionString)) 43 | { 44 | using (SqlCommand command = new SqlCommand(commandString, connection)) 45 | { 46 | await connection.OpenAsync(); 47 | using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection)) 48 | { 49 | object[] fieldNames = new object[reader.FieldCount]; 50 | for (int i = 0; i < reader.FieldCount; i++) 51 | { 52 | fieldNames[i] = reader.GetName(i); 53 | } 54 | rows.Add(fieldNames); 55 | 56 | IDataRecord record = (IDataRecord)reader; 57 | while (await reader.ReadAsync()) 58 | { 59 | object[] resultRecord = new object[record.FieldCount]; 60 | record.GetValues(resultRecord); 61 | for (int i = 0; i < record.FieldCount; i++) 62 | { 63 | Type type = record.GetFieldType(i); 64 | if (type == typeof(byte[]) || type == typeof(char[])) 65 | { 66 | resultRecord[i] = Convert.ToBase64String((byte[])resultRecord[i]); 67 | } 68 | else if (type == typeof(Guid) || type == typeof(DateTime)) 69 | { 70 | resultRecord[i] = resultRecord[i].ToString(); 71 | } 72 | else if (type == typeof(IDataReader)) 73 | { 74 | resultRecord[i] = ""; 75 | } 76 | } 77 | 78 | rows.Add(resultRecord); 79 | } 80 | } 81 | } 82 | } 83 | 84 | return rows; 85 | } 86 | 87 | async Task ExecuteNonQuery(string connectionString, string commandString) 88 | { 89 | using (SqlConnection connection = new SqlConnection(connectionString)) 90 | { 91 | using (SqlCommand command = new SqlCommand(commandString, connection)) 92 | { 93 | await connection.OpenAsync(); 94 | return await command.ExecuteNonQueryAsync(); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /samples/202_sql.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var sql = edge.func('202_sql.csx'); 6 | 7 | sql('select top 2 * from Products', function (error, result) { 8 | if (error) throw error; 9 | console.log(result); 10 | }); 11 | -------------------------------------------------------------------------------- /samples/203_x509store.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var listCertificates = edge.func(function() {/* 6 | #r "System.dll" 7 | 8 | using System.Collections.Generic; 9 | using System.Security.Cryptography.X509Certificates; 10 | 11 | async (dynamic data) => 12 | { 13 | X509Store store = new X509Store( 14 | (string)data.storeName, 15 | (StoreLocation)Enum.Parse(typeof(StoreLocation), (string)data.storeLocation)); 16 | store.Open(OpenFlags.ReadOnly); 17 | try 18 | { 19 | List result = new List(); 20 | foreach (X509Certificate2 certificate in store.Certificates) 21 | { 22 | result.Add(certificate.Subject); 23 | } 24 | 25 | return result; 26 | } 27 | finally 28 | { 29 | store.Close(); 30 | } 31 | } 32 | */}); 33 | 34 | var result = listCertificates({ storeName: 'My', storeLocation: 'LocalMachine' }, true); 35 | console.log(result); 36 | -------------------------------------------------------------------------------- /samples/204_event_log.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var writeEventLog = edge.func(function() {/* 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | 9 | async (dynamic parameters) => 10 | { 11 | var source = (string)parameters.source; 12 | var log = (string)parameters.log; 13 | if (!EventLog.SourceExists(source)) 14 | { 15 | EventLog.CreateEventSource(source, log); 16 | } 17 | 18 | EventLog.WriteEntry( 19 | source, 20 | (string)parameters.message, 21 | (EventLogEntryType)Enum.Parse( 22 | typeof(EventLogEntryType), (string)parameters.type), 23 | (int)parameters.id 24 | ); 25 | 26 | return null; 27 | } 28 | */}); 29 | 30 | writeEventLog({ 31 | source: 'Edge.js sample application', 32 | log: 'Application', 33 | type: 'Information', 34 | message: 'Hello from node.js. The time is ' + new Date(), 35 | id: 31415 36 | }, true); 37 | 38 | console.log('Success. Check EventViewer.'); 39 | -------------------------------------------------------------------------------- /samples/205_soap.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var convertKilograms = edge.func('205_soap.csx'); 6 | 7 | convertKilograms(123, function (error, result) { 8 | if (error) throw error; 9 | console.log(result); 10 | }); 11 | -------------------------------------------------------------------------------- /samples/206_registry_read.js: -------------------------------------------------------------------------------- 1 | var edge = require('../lib/edge'); 2 | 3 | var readRegistery = edge.func(function () {/* 4 | using Microsoft.Win32; 5 | 6 | async (dynamic input) => 7 | { 8 | return Registry.GetValue((string) input.keyName, (string) input.valueName, null); 9 | } 10 | */}); 11 | 12 | readRegistery({ 13 | keyName: 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\4.0', 14 | valueName: 'MSBuildOverrideTasksPath' 15 | }, function (err, result) { 16 | if (err) { 17 | throw err; 18 | } 19 | 20 | console.log(result); 21 | }); -------------------------------------------------------------------------------- /samples/206_registry_write.js: -------------------------------------------------------------------------------- 1 | var edge = require('../lib/edge'); 2 | 3 | var writeRegistery = edge.func(function () {/* 4 | using Microsoft.Win32; 5 | 6 | async (dynamic input) => 7 | { 8 | Registry.SetValue((string)input.keyName, (string)input.valueName, input.value); 9 | return null; 10 | } 11 | */}); 12 | 13 | writeRegistery({ 14 | keyName: 'HKEY_CURRENT_USER\\Environment', 15 | valueName: 'MyCustomValue', 16 | value: 1050 17 | }, function (err) { 18 | if (err) { 19 | throw err; 20 | } 21 | 22 | console.log('Done!'); 23 | }); -------------------------------------------------------------------------------- /samples/207_unzip.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge') 4 | , path = require('path'); 5 | 6 | var unzipDirectory = edge.func(function() {/* 7 | #r "System.IO.Compression.FileSystem.dll" 8 | 9 | using System.IO.Compression; 10 | 11 | async (dynamic input) => 12 | { 13 | await Task.Run(async () => { 14 | ZipFile.ExtractToDirectory((string)input.source, (string)input.destination); 15 | }); 16 | 17 | return null; 18 | } 19 | */}); 20 | 21 | var params = { 22 | source: path.join(__dirname, '..', 'samples.zip'), 23 | destination: path.join(__dirname, '..', 'samples_tmp') 24 | }; 25 | 26 | unzipDirectory(params, function (error) { 27 | if (error) throw error; 28 | console.log('The ..\\samples.zip archive has been decompressed to ..\\samples_tmp directory.'); 29 | }); 30 | -------------------------------------------------------------------------------- /samples/207_zip.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge') 4 | , path = require('path'); 5 | 6 | var zipDirectory = edge.func(function() {/* 7 | #r "System.IO.Compression.FileSystem.dll" 8 | 9 | using System.IO.Compression; 10 | 11 | async (dynamic input) => 12 | { 13 | await Task.Run(async () => { 14 | ZipFile.CreateFromDirectory((string)input.source, (string)input.destination); 15 | }); 16 | 17 | return null; 18 | } 19 | */}); 20 | 21 | var params = { 22 | source: path.join(__dirname, '..', 'samples'), 23 | destination: path.join(__dirname, '..', 'samples.zip') 24 | }; 25 | 26 | zipDirectory(params, function (error) { 27 | if (error) throw error; 28 | console.log('The samples directory has been compressed to ..\\samples.zip file.'); 29 | }); 30 | -------------------------------------------------------------------------------- /samples/208_convertImage.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge') 4 | , path = require('path'); 5 | 6 | var convertImage = edge.func(function() {/* 7 | #r "System.Drawing.dll" 8 | 9 | using System; 10 | using System.Threading.Tasks; 11 | using System.Collections.Generic; 12 | using System.Drawing; 13 | using System.Drawing.Imaging; 14 | 15 | class Startup 16 | { 17 | static IDictionary formats = new Dictionary 18 | { 19 | { "jpg", ImageFormat.Jpeg }, 20 | { "bmp", ImageFormat.Bmp }, 21 | { "gif", ImageFormat.Gif }, 22 | { "tiff", ImageFormat.Tiff }, 23 | { "png", ImageFormat.Png } 24 | }; 25 | 26 | public async Task Invoke(IDictionary input) 27 | { 28 | await Task.Run(async () => { 29 | using (Image image = Image.FromFile((string)input["source"])) 30 | { 31 | image.Save((string)input["destination"], formats[(string)input["toType"]]); 32 | } 33 | }); 34 | 35 | return null; 36 | } 37 | } 38 | */}); 39 | 40 | var params = { 41 | source: path.join(__dirname, 'edge.png'), 42 | destination: path.join(__dirname, 'edge.jpg'), 43 | toType: 'jpg' 44 | }; 45 | 46 | convertImage(params, function (error) { 47 | if (error) throw error; 48 | console.log('The edge.png has been asynchronously converted to edge.jpg.'); 49 | }); 50 | -------------------------------------------------------------------------------- /samples/210_windows_authentication.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge') 4 | , http = require('http'); 5 | 6 | var authenticate = edge.func(function() {/* 7 | using System; 8 | using System.Threading.Tasks; 9 | using System.Runtime.InteropServices; 10 | using System.Security.Principal; 11 | 12 | class Startup 13 | { 14 | 15 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 16 | public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, 17 | int dwLogonType, int dwLogonProvider, out IntPtr phToken); 18 | 19 | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 20 | public extern static bool CloseHandle(IntPtr handle); 21 | 22 | public async Task Invoke(dynamic input) 23 | { 24 | return await Task.Run(() => { 25 | IntPtr token; 26 | if (!Startup.LogonUser(input.user, null, input.password, 3, 0, out token)) 27 | { 28 | throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); 29 | } 30 | 31 | try { 32 | using (WindowsIdentity id = new WindowsIdentity(token)) 33 | { 34 | return new { 35 | name = id.Name, 36 | sid = id.User.ToString() 37 | }; 38 | } 39 | } 40 | finally { 41 | Startup.CloseHandle(token); 42 | } 43 | }); 44 | } 45 | } 46 | */}); 47 | 48 | http.createServer(function (req, res) { 49 | function challange() { 50 | res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=""' }); 51 | res.end(); 52 | } 53 | 54 | if (req.headers.authorization && req.headers.authorization.indexOf('Basic ') === 0) { 55 | var tokens = new Buffer(req.headers.authorization.substring(6), 'base64').toString('utf8').split(':'); 56 | if (!tokens || tokens.length !== 2 || tokens[0] === 'noone' && tokens[1] === 'noone') { 57 | challange(); 58 | } 59 | else { 60 | authenticate({ user: tokens[0], password: tokens[1] }, function (error, result) { 61 | if (error) { 62 | console.log(error); 63 | challange(); 64 | } 65 | else { 66 | res.writeHead(200, { 'Content-Type': 'text/html' }); 67 | res.write('

Welcome ' + result.name + ' (' + result.sid + ')'); 68 | res.end('

Logout'); 69 | } 70 | }) 71 | } 72 | } 73 | else { 74 | challange(); 75 | } 76 | }).listen(process.env.PORT || 8080); 77 | -------------------------------------------------------------------------------- /samples/211_events.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge'); 4 | 5 | var subscribe = edge.func(function() {/* 6 | async (dynamic input) => 7 | { 8 | // Create a timer with the specifed interval. 9 | // Conceptually this can be any event source. 10 | 11 | var timer = new System.Timers.Timer(input.interval); 12 | 13 | // Hook up the Elapsed event for the timer and delegate 14 | // the call to a Node.js event handler. 15 | // Depending on the EventArgs, the data may need to be transformed 16 | // if it cannot be directly marshaled by Edge.js. 17 | 18 | timer.Elapsed += (Object source, System.Timers.ElapsedEventArgs e) => { 19 | ((Func>)input.event_handler)(e).Start(); 20 | }; 21 | 22 | // Start the timer 23 | 24 | timer.Enabled = true; 25 | 26 | // Return a function that can be used by Node.js to 27 | // unsubscribe from the event source. 28 | 29 | return (Func>)(async (dynamic data) => { 30 | timer.Enabled = false; 31 | return null; 32 | }); 33 | } 34 | */}); 35 | 36 | subscribe({ 37 | interval: 2000, 38 | event_handler: function (data, cb) { 39 | console.log('Received event', data); 40 | cb(); 41 | } 42 | }, function (error, unsubscribe) { 43 | if (error) throw error; 44 | console.log('Subscribed to .NET events. Unsubscribing in 7 seconds...'); 45 | setTimeout(function () { 46 | unsubscribe(null, function (error) { 47 | if (error) throw error; 48 | console.log('Unsubscribed from .NET events.'); 49 | console.log('Waiting 5 seconds before exit to show that no more events are generated...') 50 | setTimeout(function () {}, 5000); 51 | }); 52 | }, 7000); 53 | }); 54 | -------------------------------------------------------------------------------- /samples/301_cspyfsps.js: -------------------------------------------------------------------------------- 1 | // Overview of edge.js: http://tjanczuk.github.com/edge 2 | 3 | var edge = require('../lib/edge') 4 | , async = require('async'); 5 | 6 | var helloCs = edge.func(function () {/* 7 | async (input) => 8 | { 9 | return "C# welcomes " + input.ToString(); 10 | } 11 | */}); 12 | 13 | var helloPy = edge.func('py', function () {/* 14 | def hello(input): 15 | return "Python welcomes " + input 16 | 17 | lambda x: hello(x) 18 | */}); 19 | 20 | var helloFs = edge.func('fs', function () {/* 21 | fun input -> async { 22 | return "F# welcomes " + input.ToString() 23 | } 24 | */}); 25 | 26 | var helloPs = edge.func('ps', function () {/* 27 | "PowerShell welcomes $inputFromJS" 28 | */}); 29 | 30 | async.waterfall([ 31 | function (cb) { cb(null, 'Node.js'); }, 32 | 33 | helloFs, 34 | helloCs, 35 | helloPy, 36 | helloPs 37 | ], function (error, result) { 38 | console.log(error || result[0]); 39 | }); -------------------------------------------------------------------------------- /samples/edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agracio/edge-js/772ad2548a99d05c7de635d16a60a4779f7e5d97/samples/edge.png -------------------------------------------------------------------------------- /samples/readme.txt: -------------------------------------------------------------------------------- 1 | Foundations: 2 | 3 | 101_hello_lambda.js - prescriptive interface pattern 4 | 102_hello_function.js - multiline function comment 5 | 103_hello_file.js - separate file 6 | 104_add7_class.js - entire class instead of lambda 7 | 105_add7_dll.js - pre-compiled DLL 8 | On Windows: 9 | csc.exe /target:library /debug Sample105.cs 10 | On Mono (MacOS, Linux): 11 | mcs -sdk:4.5 Sample105.cs -target:library 12 | start repl, attach VS, call func, show debugging 13 | 106_marshal_v82cls.js - data from V8 to CLR 14 | 107_marshal_clr2v8.js - data from CLR to V8 15 | 108_func.js - marshal func from v8 to CLR and call node from .NET 16 | 109_sync.js - async and sync calling conventions 17 | 18 | Scenarios: 19 | 20 | 201_worker.js - CPU bound operation 21 | 202_sql.js - access SQL with async ADO.NET 22 | set OWIN_SQL_CONNECTION_STRING=Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True 23 | reference assemblies 24 | 206_registery - read/write registery operations 25 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/coreclrfuncinvokecontext.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | CoreClrFuncInvokeContext::CoreClrFuncInvokeContext(v8::Local callback, void* task) : task(task), uv_edge_async(NULL), resultData(NULL), resultType(0) 4 | { 5 | DBG("CoreClrFuncInvokeContext::CoreClrFuncInvokeContext"); 6 | 7 | this->callback = new Nan::Callback(v8::Local::Cast(callback)); 8 | } 9 | 10 | CoreClrFuncInvokeContext::~CoreClrFuncInvokeContext() 11 | { 12 | DBG("CoreClrFuncInvokeContext::~CoreClrFuncInvokeContext"); 13 | 14 | if (this->callback) 15 | { 16 | this->callback->Reset(); 17 | delete this->callback; 18 | this->callback = NULL; 19 | } 20 | 21 | if (this->task) 22 | { 23 | CoreClrEmbedding::FreeHandle(this->task); 24 | this->task = NULL; 25 | } 26 | 27 | if (this->resultData) 28 | { 29 | CoreClrEmbedding::FreeMarshalData(this->resultData, this->resultType); 30 | this->resultData = NULL; 31 | } 32 | } 33 | 34 | void CoreClrFuncInvokeContext::InitializeAsyncOperation() 35 | { 36 | DBG("CoreClrFuncInvokeContext::InitializeAsyncOperation"); 37 | this->uv_edge_async = V8SynchronizationContext::RegisterAction(CoreClrFuncInvokeContext::InvokeCallback, this); 38 | } 39 | 40 | void CoreClrFuncInvokeContext::TaskComplete(void* result, int resultType, int taskState, CoreClrFuncInvokeContext* context) 41 | { 42 | DBG("CoreClrFuncInvokeContext::TaskComplete"); 43 | 44 | context->resultData = result; 45 | context->resultType = resultType; 46 | context->taskState = taskState; 47 | 48 | V8SynchronizationContext::ExecuteAction(context->uv_edge_async); 49 | } 50 | 51 | void CoreClrFuncInvokeContext::TaskCompleteSynchronous(void* result, int resultType, int taskState, v8::Local callback) 52 | { 53 | DBG("CoreClrFuncInvokeContext::TaskCompleteSynchronous"); 54 | 55 | CoreClrFuncInvokeContext* context = new CoreClrFuncInvokeContext(callback, NULL); 56 | 57 | context->resultData = result; 58 | context->resultType = resultType; 59 | context->taskState = taskState; 60 | 61 | InvokeCallback(context); 62 | } 63 | 64 | void CoreClrFuncInvokeContext::InvokeCallback(void* data) 65 | { 66 | DBG("CoreClrFuncInvokeContext::InvokeCallback"); 67 | 68 | CoreClrFuncInvokeContext* context = (CoreClrFuncInvokeContext*)data; 69 | v8::Local callbackData = Nan::Null(); 70 | v8::Local errors = Nan::Null(); 71 | 72 | if (context->taskState == TaskStatusFaulted) 73 | { 74 | errors = CoreClrFunc::MarshalCLRToV8(context->resultData, context->resultType); 75 | } 76 | 77 | else 78 | { 79 | callbackData = CoreClrFunc::MarshalCLRToV8(context->resultData, context->resultType); 80 | } 81 | 82 | DBG("CoreClrFuncInvokeContext::InvokeCallback - Marshalling complete"); 83 | 84 | v8::Local argv[] = { errors, callbackData }; 85 | int argc = 2; 86 | 87 | Nan::TryCatch tryCatch; 88 | 89 | DBG("CoreClrFuncInvokeContext::InvokeCallback - calling JS callback"); 90 | 91 | Nan::AsyncResource resource("CoreClrFuncInvokeContext::InvokeCallback"); 92 | context->callback->Call(argc, argv, &resource); 93 | delete context; 94 | if (tryCatch.HasCaught()) 95 | { 96 | DBG("CoreClrFuncInvokeContext::InvokeCallback - exception in callback"); 97 | Nan::FatalException(tryCatch); 98 | } 99 | 100 | DBG("CoreClrFuncInvokeContext::InvokeCallback - Complete"); 101 | } 102 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/coreclrnodejsfunc.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | CoreClrNodejsFunc::CoreClrNodejsFunc(v8::Local function) 4 | { 5 | DBG("CoreClrNodejsFunc::CoreClrNodejsFunc"); 6 | 7 | this->Func = new Nan::Persistent; 8 | this->Func->Reset(function); 9 | } 10 | 11 | CoreClrNodejsFunc::~CoreClrNodejsFunc() 12 | { 13 | DBG("CoreClrNodejsFunc::~CoreClrNodejsFunc"); 14 | this->Func->Reset(); 15 | delete this->Func; 16 | this->Func = NULL; 17 | } 18 | 19 | void CoreClrNodejsFunc::Release(CoreClrNodejsFunc* function) 20 | { 21 | DBG("CoreClrNodejsFunc::Release"); 22 | delete function; 23 | } 24 | 25 | void CoreClrNodejsFunc::Call(void* payload, int payloadType, CoreClrNodejsFunc* functionContext, CoreClrGcHandle callbackContext, NodejsFuncCompleteFunction callbackFunction) 26 | { 27 | DBG("CoreClrNodejsFunc::Call"); 28 | 29 | CoreClrNodejsFuncInvokeContext* invokeContext = new CoreClrNodejsFuncInvokeContext(payload, payloadType, functionContext, callbackContext, callbackFunction); 30 | invokeContext->Invoke(); 31 | } 32 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/deps/deps_entry.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef __DEPS_ENTRY_H_ 5 | #define __DEPS_ENTRY_H_ 6 | 7 | #if EDGE_PLATFORM_NIX 8 | #include "../edge.h" 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #include "../pal/pal.h" 14 | 15 | struct deps_entry_t 16 | { 17 | enum asset_types 18 | { 19 | runtime = 0, 20 | resources, 21 | native, 22 | count 23 | }; 24 | 25 | static const std::array s_known_asset_types; 26 | 27 | pal::string_t library_type; 28 | pal::string_t library_name; 29 | pal::string_t library_version; 30 | pal::string_t library_hash; 31 | asset_types asset_type; 32 | pal::string_t asset_name; 33 | pal::string_t relative_path; 34 | bool is_serviceable; 35 | bool is_rid_specific; 36 | 37 | 38 | // Given a "base" dir, yield the filepath within this directory or relative to this directory based on "look_in_base" 39 | bool to_path(const pal::string_t& base, bool look_in_base, pal::string_t* str) const; 40 | 41 | // Given a "base" dir, yield the file path within this directory. 42 | bool to_dir_path(const pal::string_t& base, pal::string_t* str) const; 43 | 44 | // Given a "base" dir, yield the relative path in the package layout. 45 | bool to_rel_path(const pal::string_t& base, pal::string_t* str) const; 46 | 47 | // Given a "base" dir, yield the relative path with package name, version in the package layout. 48 | bool to_full_path(const pal::string_t& root, pal::string_t* str) const; 49 | 50 | // Given a "base" dir, yield the relative path with package name, version in the package layout only if 51 | // the hash matches contents of the hash file. 52 | bool to_hash_matched_path(const pal::string_t& root, pal::string_t* str) const; 53 | }; 54 | 55 | #endif // __DEPS_ENTRY_H_ 56 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/deps/deps_format.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef __DEPS_FORMAT_H_ 5 | #define __DEPS_FORMAT_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../pal/pal.h" 12 | #include "deps_entry.h" 13 | #include "cpprest/json.h" 14 | 15 | void set_own_rid(pal::string_t set_rid); 16 | 17 | class deps_json_t 18 | { 19 | typedef web::json::value json_value; 20 | struct vec_t { std::vector vec; }; 21 | struct assets_t { std::array by_type; }; 22 | struct deps_assets_t { std::unordered_map libs; }; 23 | struct rid_assets_t { std::unordered_map rid_assets; }; 24 | struct rid_specific_assets_t { std::unordered_map libs; }; 25 | 26 | typedef std::unordered_map> str_to_vector_map_t; 27 | typedef str_to_vector_map_t rid_fallback_graph_t; 28 | 29 | 30 | public: 31 | deps_json_t() 32 | : m_valid(false) 33 | , m_file_exists(false) 34 | { 35 | } 36 | 37 | deps_json_t(bool portable, const pal::string_t& deps_path) 38 | : deps_json_t(portable, deps_path, m_rid_fallback_graph /* dummy */) 39 | { 40 | } 41 | 42 | deps_json_t(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& graph) 43 | : deps_json_t() 44 | { 45 | m_valid = load(portable, deps_path, graph); 46 | } 47 | 48 | const std::vector& get_entries(deps_entry_t::asset_types type) 49 | { 50 | assert(type < deps_entry_t::asset_types::count); 51 | return m_deps_entries[type]; 52 | } 53 | 54 | bool has_package(const pal::string_t& name, const pal::string_t& ver) const; 55 | 56 | bool exists() 57 | { 58 | return m_file_exists; 59 | } 60 | 61 | bool is_valid() 62 | { 63 | return m_valid; 64 | } 65 | 66 | const rid_fallback_graph_t& get_rid_fallback_graph() 67 | { 68 | return m_rid_fallback_graph; 69 | } 70 | 71 | const deps_entry_t& try_ni(const deps_entry_t& entry) const; 72 | 73 | private: 74 | bool load_standalone(const json_value& json, const pal::string_t& target_name); 75 | bool load_portable(const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph); 76 | bool load(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph); 77 | bool process_runtime_targets(const json_value& json, const pal::string_t& target_name, const rid_fallback_graph_t& rid_fallback_graph, rid_specific_assets_t* p_assets); 78 | bool process_targets(const json_value& json, const pal::string_t& target_name, deps_assets_t* p_assets); 79 | 80 | void reconcile_libraries_with_targets( 81 | const json_value& json, 82 | const std::function& library_exists_fn, 83 | const std::function&(const pal::string_t&, int, bool*)>& get_rel_paths_by_asset_type_fn); 84 | 85 | bool perform_rid_fallback(rid_specific_assets_t* portable_assets, const rid_fallback_graph_t& rid_fallback_graph); 86 | 87 | std::vector m_deps_entries[deps_entry_t::asset_types::count]; 88 | 89 | deps_assets_t m_assets; 90 | rid_specific_assets_t m_rid_assets; 91 | 92 | std::unordered_map m_ni_entries; 93 | rid_fallback_graph_t m_rid_fallback_graph; 94 | bool m_file_exists; 95 | bool m_valid; 96 | }; 97 | 98 | #endif // __DEPS_FORMAT_H_ 99 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/fxr/fx_muxer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | class corehost_init_t; 5 | class runtime_config_t; 6 | struct fx_ver_t; 7 | 8 | #include "../host/libhost.h" 9 | 10 | int execute_app( 11 | const pal::string_t& impl_dll_dir, 12 | corehost_init_t* init, 13 | const int argc, 14 | const pal::char_t* argv[]); 15 | 16 | class fx_muxer_t 17 | { 18 | public: 19 | static int execute(const int argc, const pal::char_t* argv[]); 20 | static pal::string_t resolve_fx_dir(host_mode_t mode, const pal::string_t& own_dir, const runtime_config_t& config, const pal::string_t& specified_fx_version); 21 | static bool resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::string_t* cli_sdk); 22 | private: 23 | static int read_config_and_execute( 24 | const pal::string_t& own_dir, 25 | const pal::string_t& app_candidate, 26 | const std::unordered_map>& opts, 27 | int new_argc, const pal::char_t** new_argv, host_mode_t mode); 28 | static int parse_args_and_execute(const pal::string_t& own_dir, const pal::string_t& own_dll, int argoff, int argc, const pal::char_t* argv[], bool exec_mode, host_mode_t mode, bool* can_execute); 29 | static bool resolve_hostpolicy_dir(host_mode_t mode, 30 | const pal::string_t& own_dir, 31 | const pal::string_t& fx_dir, 32 | const pal::string_t& app_or_deps_dir, 33 | const pal::string_t& specified_deps_file, 34 | const pal::string_t& specified_fx_version, 35 | const std::vector& probe_realpaths, 36 | const runtime_config_t& config, 37 | pal::string_t* impl_dir); 38 | static pal::string_t resolve_cli_version(const pal::string_t& global); 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/fxr/fx_ver.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef __FX_VER_H__ 5 | #define __FX_VER_H__ 6 | 7 | #include "../pal/pal.h" 8 | 9 | // Note: This is not SemVer (esp., in comparing pre-release part, fx_ver_t does not 10 | // compare multiple dot separated identifiers individually.) ex: 1.0.0-beta.2 vs. 1.0.0-beta.11 11 | struct fx_ver_t 12 | { 13 | fx_ver_t(int major, int minor, int patch); 14 | fx_ver_t(int major, int minor, int patch, const pal::string_t& pre); 15 | fx_ver_t(int major, int minor, int patch, const pal::string_t& pre, const pal::string_t& build); 16 | 17 | int get_major() const { return m_major; } 18 | int get_minor() const { return m_minor; } 19 | int get_patch() const { return m_patch; } 20 | 21 | void set_major(int m) { m_major = m; } 22 | void set_minor(int m) { m_minor = m; } 23 | void set_patch(int p) { m_patch = p; } 24 | 25 | bool is_prerelease() const { return !m_pre.empty(); } 26 | 27 | pal::string_t as_str() const; 28 | pal::string_t prerelease_glob() const; 29 | pal::string_t patch_glob() const; 30 | 31 | bool operator ==(const fx_ver_t& b) const; 32 | bool operator !=(const fx_ver_t& b) const; 33 | bool operator <(const fx_ver_t& b) const; 34 | bool operator >(const fx_ver_t& b) const; 35 | 36 | static bool parse(const pal::string_t& ver, fx_ver_t* fx_ver, bool parse_only_production = false); 37 | 38 | private: 39 | int m_major; 40 | int m_minor; 41 | int m_patch; 42 | pal::string_t m_pre; 43 | pal::string_t m_build; 44 | 45 | static int compare(const fx_ver_t&a, const fx_ver_t& b); 46 | }; 47 | 48 | #endif // __FX_VER_H__ -------------------------------------------------------------------------------- /src/CoreCLREmbedding/host/args.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include "args.h" 5 | #include "../pal/pal_utils.h" 6 | #include "coreclr.h" 7 | #include "libhost.h" 8 | 9 | arguments_t::arguments_t() : 10 | managed_application(_X("")), 11 | own_path(_X("")), 12 | app_dir(_X("")), 13 | app_argc(0), 14 | app_argv(nullptr), 15 | dotnet_packages_cache(_X("")), 16 | core_servicing(_X("")), 17 | deps_path(_X("")) 18 | { 19 | } 20 | 21 | bool parse_arguments( 22 | const pal::string_t& deps_path, 23 | const std::vector& probe_paths, 24 | host_mode_t mode, 25 | const int argc, const pal::char_t* argv[], arguments_t* arg_out) 26 | { 27 | arguments_t& args = *arg_out; 28 | // Get the full name of the application 29 | if (!pal::get_own_executable_path(&args.own_path) || !pal::realpath(&args.own_path)) 30 | { 31 | trace::error(_X("Failed to resolve full path of the current executable [%s]"), args.own_path.c_str()); 32 | return false; 33 | } 34 | 35 | auto own_name = get_filename(args.own_path); 36 | auto own_dir = get_directory(args.own_path); 37 | 38 | if (mode != host_mode_t::standalone) 39 | { 40 | // corerun mode. First argument is managed app 41 | if (argc < 2) 42 | { 43 | return false; 44 | } 45 | args.managed_application = pal::string_t(argv[1]); 46 | if (!pal::realpath(&args.managed_application)) 47 | { 48 | trace::error(_X("Failed to locate managed application [%s]"), args.managed_application.c_str()); 49 | return false; 50 | } 51 | args.app_dir = get_directory(args.managed_application); 52 | args.app_argc = argc - 2; 53 | args.app_argv = &argv[2]; 54 | } 55 | else 56 | { 57 | // coreconsole mode. Find the managed app in the same directory 58 | pal::string_t managed_app(own_dir); 59 | managed_app.push_back(DIR_SEPARATOR); 60 | managed_app.append(get_executable(own_name)); 61 | managed_app.append(_X(".dll")); 62 | args.managed_application = managed_app; 63 | if (!pal::realpath(&args.managed_application)) 64 | { 65 | trace::error(_X("Failed to locate managed application [%s]"), args.managed_application.c_str()); 66 | return false; 67 | } 68 | args.app_dir = own_dir; 69 | args.app_argv = &argv[1]; 70 | args.app_argc = argc - 1; 71 | } 72 | 73 | if (!deps_path.empty()) 74 | { 75 | args.deps_path = deps_path; 76 | args.app_dir = get_directory(args.deps_path); 77 | } 78 | 79 | for (const auto& probe : probe_paths) 80 | { 81 | args.probe_paths.push_back(probe); 82 | } 83 | 84 | if (args.deps_path.empty()) 85 | { 86 | const auto& app_base = args.app_dir; 87 | auto app_name = get_filename(args.managed_application); 88 | 89 | args.deps_path.reserve(app_base.length() + 1 + app_name.length() + 5); 90 | args.deps_path.append(app_base); 91 | args.deps_path.push_back(DIR_SEPARATOR); 92 | args.deps_path.append(app_name, 0, app_name.find_last_of(_X("."))); 93 | args.deps_path.append(_X(".deps.json")); 94 | } 95 | 96 | pal::getenv(_X("DOTNET_HOSTING_OPTIMIZATION_CACHE"), &args.dotnet_packages_cache); 97 | pal::get_default_servicing_directory(&args.core_servicing); 98 | 99 | return true; 100 | } 101 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/host/coreclr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef CLR_H 5 | #define CLR_H 6 | 7 | #include "../pal/pal.h" 8 | #include "../pal/trace.h" 9 | 10 | namespace coreclr 11 | { 12 | typedef void* host_handle_t; 13 | typedef unsigned int domain_id_t; 14 | 15 | static pal::dll_t g_coreclr = nullptr; 16 | 17 | bool bind(const pal::string_t& libcoreclr_path); 18 | 19 | void unload(); 20 | 21 | pal::hresult_t initialize( 22 | const char* exe_path, 23 | const char* app_domain_friendly_name, 24 | const char** property_keys, 25 | const char** property_values, 26 | int property_count, 27 | host_handle_t* host_handle, 28 | domain_id_t* domain_id); 29 | 30 | pal::hresult_t shutdown(host_handle_t host_handle, domain_id_t domain_id); 31 | 32 | pal::hresult_t execute_assembly( 33 | host_handle_t host_handle, 34 | domain_id_t domain_id, 35 | int argc, 36 | const char** argv, 37 | const char* managed_assembly_path, 38 | unsigned int* exit_code); 39 | 40 | pal::hresult_t create_delegate( 41 | coreclr::host_handle_t hostHandle, 42 | unsigned int domainId, 43 | const char* assemblyName, 44 | const char* typeName, 45 | const char* methodName, 46 | void** delegate); 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/host/error_codes.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef __ERROR_CODES_H__ 5 | #define __ERROR_CODES_H__ 6 | enum StatusCode 7 | { 8 | Success = 0, 9 | InvalidArgFailure = 0x80008081, 10 | CoreHostLibLoadFailure = 0x80008082, 11 | CoreHostLibMissingFailure = 0x80008083, 12 | CoreHostEntryPointFailure = 0x80008084, 13 | CoreHostCurExeFindFailure = 0x80008085, 14 | CoreHostResolveModeFailure = 0x80008086, 15 | CoreClrResolveFailure = 0x80008087, 16 | CoreClrBindFailure = 0x80008088, 17 | CoreClrInitFailure = 0x80008089, 18 | CoreClrExeFailure = 0x8000808a, 19 | ResolverInitFailure = 0x8000808b, 20 | ResolverResolveFailure = 0x8000808c, 21 | LibHostCurExeFindFailure = 0x8000808d, 22 | LibHostInitFailure = 0x8000808e, 23 | LibHostMuxFailure = 0x8000808f, 24 | LibHostExecModeFailure = 0x80008090, 25 | LibHostSdkFindFailure = 0x80008091, 26 | LibHostInvalidArgs = 0x80008092, 27 | InvalidConfigFile = 0x80008093, 28 | AppArgNotRunnable = 0x80008094 29 | }; 30 | #endif // __ERROR_CODES_H__ 31 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/host/runtime_config.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef __RUNTIME_CONFIG_H__ 5 | #define __RUNTIME_CONFIG_H__ 6 | 7 | #include 8 | 9 | #include "../pal/pal.h" 10 | #include "cpprest/json.h" 11 | 12 | typedef web::json::value json_value; 13 | 14 | class runtime_config_t 15 | { 16 | public: 17 | runtime_config_t(const pal::string_t& path, const pal::string_t& dev_path); 18 | bool is_valid() { return m_valid; } 19 | const pal::string_t& get_path() { return m_path; } 20 | const pal::string_t& get_dev_path() { return m_dev_path; } 21 | const pal::string_t& get_gc_server() const; 22 | const pal::string_t& get_fx_version() const; 23 | const pal::string_t& get_fx_name() const; 24 | const std::list& get_probe_paths() const; 25 | bool get_patch_roll_fwd() const; 26 | bool get_prerelease_roll_fwd() const; 27 | bool get_portable() const; 28 | bool parse_opts(const json_value& opts); 29 | void config_kv(std::vector*, std::vector*) const; 30 | 31 | private: 32 | bool ensure_parsed(); 33 | bool ensure_dev_config_parsed(); 34 | 35 | std::unordered_map m_properties; 36 | std::vector m_prop_keys; 37 | std::vector m_prop_values; 38 | std::list m_probe_paths; 39 | pal::string_t m_fx_name; 40 | pal::string_t m_fx_ver; 41 | bool m_patch_roll_fwd; 42 | bool m_prerelease_roll_fwd; 43 | 44 | pal::string_t m_dev_path; 45 | pal::string_t m_path; 46 | bool m_portable; 47 | bool m_valid; 48 | }; 49 | #endif // __RUNTIME_CONFIG_H__ -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/LICENSE.txt: -------------------------------------------------------------------------------- 1 | https://github.com/Microsoft/cpprestsdk 2 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/include/cpprest/details/cpprest_compat.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * Copyright (C) Microsoft. All rights reserved. 3 | * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. 4 | * 5 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 6 | * 7 | * Standard macros and definitions. 8 | * This header has minimal dependency on windows headers and is safe for use in the public API 9 | * 10 | * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 11 | * 12 | * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 13 | ****/ 14 | 15 | #pragma once 16 | 17 | #if defined(_WIN32) 18 | 19 | #if _MSC_VER >= 1900 20 | #define CPPREST_NOEXCEPT noexcept 21 | #define CPPREST_CONSTEXPR constexpr 22 | #else 23 | #define CPPREST_NOEXCEPT 24 | #define CPPREST_CONSTEXPR const 25 | #endif // _MSC_VER >= 1900 26 | 27 | #include 28 | 29 | #else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv 30 | 31 | #define __declspec(x) __attribute__((x)) 32 | #define dllimport 33 | #define novtable /* no novtable equivalent */ 34 | #define __assume(x) \ 35 | do \ 36 | { \ 37 | if (!(x)) __builtin_unreachable(); \ 38 | } while (false) 39 | #define CPPREST_NOEXCEPT noexcept 40 | #define CPPREST_CONSTEXPR constexpr 41 | 42 | #include 43 | #define _ASSERTE(x) assert(x) 44 | 45 | // No SAL on non Windows platforms 46 | #include "cpprest/details/nosal.h" 47 | 48 | #if !defined(__cdecl) 49 | #if defined(cdecl) 50 | #define __cdecl __attribute__((cdecl)) 51 | #else // ^^^ defined cdecl ^^^ // vvv !defined cdecl vvv 52 | #define __cdecl 53 | #endif // defined cdecl 54 | #endif // not defined __cdecl 55 | 56 | #if defined(__ANDROID__) 57 | // This is needed to disable the use of __thread inside the boost library. 58 | // Android does not support thread local storage -- if boost is included 59 | // without this macro defined, it will create references to __tls_get_addr 60 | // which (while able to link) will not be available at runtime and prevent 61 | // the .so from loading. 62 | #if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION 63 | #define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION 64 | #endif // not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION 65 | #endif // defined(__ANDROID__) 66 | 67 | #ifdef __clang__ 68 | #include 69 | #endif // __clang__ 70 | #endif // _WIN32 71 | 72 | #ifdef _NO_ASYNCRTIMP 73 | #define _ASYNCRTIMP 74 | #define _ASYNCRTIMP_TYPEINFO 75 | #else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv 76 | #ifdef _ASYNCRT_EXPORT 77 | #define _ASYNCRTIMP __declspec(dllexport) 78 | #else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv 79 | #define _ASYNCRTIMP __declspec(dllimport) 80 | #endif // _ASYNCRT_EXPORT 81 | 82 | #if defined(_WIN32) 83 | #define _ASYNCRTIMP_TYPEINFO 84 | #else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv 85 | #define _ASYNCRTIMP_TYPEINFO __attribute__((visibility("default"))) 86 | #endif // _WIN32 87 | 88 | #endif // _NO_ASYNCRTIMP 89 | 90 | #ifdef CASABLANCA_DEPRECATION_NO_WARNINGS 91 | #define CASABLANCA_DEPRECATED(x) 92 | #else 93 | #define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x)) 94 | #endif // CASABLANCA_DEPRECATION_NO_WARNINGS 95 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/include/cpprest/details/nosal.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * Copyright (C) Microsoft. All rights reserved. 3 | * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. 4 | * 5 | * 6 | * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 7 | * 8 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 9 | ***/ 10 | 11 | #pragma once 12 | // selected MS SAL annotations 13 | 14 | #ifdef _In_ 15 | #undef _In_ 16 | #endif 17 | #define _In_ 18 | 19 | #ifdef _Inout_ 20 | #undef _Inout_ 21 | #endif 22 | #define _Inout_ 23 | 24 | #ifdef _Out_ 25 | #undef _Out_ 26 | #endif 27 | #define _Out_ 28 | 29 | #ifdef _In_z_ 30 | #undef _In_z_ 31 | #endif 32 | #define _In_z_ 33 | 34 | #ifdef _Out_z_ 35 | #undef _Out_z_ 36 | #endif 37 | #define _Out_z_ 38 | 39 | #ifdef _Inout_z_ 40 | #undef _Inout_z_ 41 | #endif 42 | #define _Inout_z_ 43 | 44 | #ifdef _In_opt_ 45 | #undef _In_opt_ 46 | #endif 47 | #define _In_opt_ 48 | 49 | #ifdef _Out_opt_ 50 | #undef _Out_opt_ 51 | #endif 52 | #define _Out_opt_ 53 | 54 | #ifdef _Inout_opt_ 55 | #undef _Inout_opt_ 56 | #endif 57 | #define _Inout_opt_ 58 | 59 | #ifdef _Out_writes_ 60 | #undef _Out_writes_ 61 | #endif 62 | #define _Out_writes_(x) 63 | 64 | #ifdef _Out_writes_opt_ 65 | #undef _Out_writes_opt_ 66 | #endif 67 | #define _Out_writes_opt_(x) 68 | 69 | #ifdef _In_reads_ 70 | #undef _In_reads_ 71 | #endif 72 | #define _In_reads_(x) 73 | 74 | #ifdef _Inout_updates_bytes_ 75 | #undef _Inout_updates_bytes_ 76 | #endif 77 | #define _Inout_updates_bytes_(x) 78 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/include/pplx/pplxconv.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * Copyright (C) Microsoft. All rights reserved. 3 | * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. 4 | * 5 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 6 | * 7 | * Utilities to convert between PPL tasks and PPLX tasks 8 | * 9 | * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 10 | * 11 | * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 12 | ****/ 13 | 14 | #pragma once 15 | 16 | #ifndef _PPLXCONV_H 17 | #define _PPLXCONV_H 18 | 19 | #ifndef _WIN32 20 | #error This is only supported on Windows 21 | #endif 22 | 23 | #if defined(_MSC_VER) && (_MSC_VER >= 1700) && (_MSC_VER < 1800) && !CPPREST_FORCE_PPLX 24 | 25 | #include "pplx/pplxtasks.h" 26 | #include 27 | 28 | namespace pplx 29 | { 30 | namespace _Ppl_conv_helpers 31 | { 32 | template 33 | auto _Set_value(_Tc _Tcp, const _F& _Func) -> decltype(_Tcp.set(_Func())) 34 | { 35 | return _Tcp.set(_Func()); 36 | } 37 | 38 | template 39 | auto _Set_value(_Tc _Tcp, const _F& _Func, ...) -> decltype(_Tcp.set()) 40 | { 41 | _Func(); 42 | return _Tcp.set(); 43 | } 44 | 45 | template 46 | _OtherTaskType _Convert_task(_TaskType _Task) 47 | { 48 | _OtherTCEType _Tc; 49 | _Task.then([_Tc](_TaskType _Task2) { 50 | try 51 | { 52 | _Ppl_conv_helpers::_Set_value(_Tc, [=] { return _Task2.get(); }); 53 | } 54 | catch (...) 55 | { 56 | _Tc.set_exception(std::current_exception()); 57 | } 58 | }); 59 | _OtherTaskType _T_other(_Tc); 60 | return _T_other; 61 | } 62 | } // namespace _Ppl_conv_helpers 63 | 64 | template 65 | concurrency::task<_TaskType> pplx_task_to_concurrency_task(pplx::task<_TaskType> _Task) 66 | { 67 | return _Ppl_conv_helpers::_Convert_task, 68 | concurrency::task<_TaskType>, 69 | concurrency::task_completion_event<_TaskType>>(_Task); 70 | } 71 | 72 | template 73 | pplx::task<_TaskType> concurrency_task_to_pplx_task(concurrency::task<_TaskType> _Task) 74 | { 75 | return _Ppl_conv_helpers::_Convert_task, 76 | pplx::task<_TaskType>, 77 | pplx::task_completion_event<_TaskType>>(_Task); 78 | } 79 | } // namespace pplx 80 | 81 | #endif 82 | 83 | #endif // _PPLXCONV_H 84 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/include/pplx/threadpool.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * Copyright (C) Microsoft. All rights reserved. 3 | * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. 4 | * 5 | * 6 | * Simple Linux implementation of a static thread pool. 7 | * 8 | * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 9 | * 10 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 11 | ***/ 12 | #pragma once 13 | 14 | #if defined(__clang__) 15 | #pragma clang diagnostic push 16 | #pragma clang diagnostic ignored "-Wconversion" 17 | #pragma clang diagnostic ignored "-Wunreachable-code" 18 | #pragma clang diagnostic ignored "-Winfinite-recursion" 19 | #endif 20 | #include "boost/asio.hpp" 21 | #if defined(__clang__) 22 | #pragma clang diagnostic pop 23 | #endif 24 | 25 | #if defined(__ANDROID__) 26 | #include "pplx/pplx.h" 27 | #include 28 | #include 29 | #endif 30 | 31 | #include "cpprest/details/cpprest_compat.h" 32 | 33 | namespace crossplat 34 | { 35 | #if defined(__ANDROID__) 36 | // IDEA: Break this section into a separate android/jni header 37 | extern std::atomic JVM; 38 | JNIEnv* get_jvm_env(); 39 | 40 | struct java_local_ref_deleter 41 | { 42 | void operator()(jobject lref) const { crossplat::get_jvm_env()->DeleteLocalRef(lref); } 43 | }; 44 | 45 | template 46 | using java_local_ref = std::unique_ptr::type, java_local_ref_deleter>; 47 | #endif 48 | 49 | class threadpool 50 | { 51 | public: 52 | _ASYNCRTIMP static threadpool& shared_instance(); 53 | _ASYNCRTIMP static std::unique_ptr __cdecl construct(size_t num_threads); 54 | 55 | virtual ~threadpool() = default; 56 | 57 | ///

58 | /// Initializes the cpprestsdk threadpool with a custom number of threads 59 | /// 60 | /// 61 | /// This function allows an application (in their main function) to initialize the cpprestsdk 62 | /// threadpool with a custom threadcount. Libraries should avoid calling this function to avoid 63 | /// a diamond problem with multiple consumers attempting to customize the pool. 64 | /// 65 | /// Thrown if the threadpool has already been initialized 66 | static void initialize_with_threads(size_t num_threads); 67 | 68 | template 69 | CASABLANCA_DEPRECATED("Use `.service().post(task)` directly.") 70 | void schedule(T task) 71 | { 72 | service().post(task); 73 | } 74 | 75 | boost::asio::io_service& service() { return m_service; } 76 | 77 | protected: 78 | threadpool(size_t num_threads) : m_service(static_cast(num_threads)) {} 79 | 80 | boost::asio::io_service m_service; 81 | }; 82 | 83 | } // namespace crossplat 84 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/json/casablanca/include/stdafx.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * ==++== 3 | * 4 | * Copyright (c) Microsoft Corporation. All rights reserved. 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * ==--== 17 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 18 | * 19 | * Pre-compiled headers 20 | * 21 | * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 22 | * 23 | * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 24 | ****/ 25 | 26 | #pragma once 27 | 28 | #if defined(__clang__) 29 | #pragma clang diagnostic push 30 | #pragma clang diagnostic ignored "-Wunused-local-typedef" 31 | #endif 32 | 33 | #include 34 | #include 35 | #ifdef _WIN32 36 | #ifdef CPPREST_TARGET_XP 37 | #include 38 | #ifndef _WIN32_WINNT 39 | #define _WIN32_WINNT _WIN32_WINNT_WS03 //Windows XP with SP2 40 | #endif 41 | #endif 42 | #include 43 | // use the debug version of the CRT if _DEBUG is defined 44 | #ifdef _DEBUG 45 | #define _CRTDBG_MAP_ALLOC 46 | #include 47 | #include 48 | #endif 49 | 50 | #ifndef WIN32_LEAN_AND_MEAN 51 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 52 | #endif 53 | 54 | #ifndef NOMINMAX 55 | #define NOMINMAX 56 | #endif 57 | 58 | #include 59 | #include 60 | 61 | // Windows Header Files: 62 | #if !defined(__cplusplus_winrt) 63 | #include 64 | 65 | #endif // #if !defined(__cplusplus_winrt) 66 | #else // LINUX or APPLE 67 | #define __STDC_LIMIT_MACROS 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include "pthread.h" 76 | #include 77 | #include 78 | #include 79 | #include 80 | #endif // _WIN32 81 | 82 | // Macro indicating the C++ Rest SDK product itself is being built. 83 | // This is to help track how many developers are directly building from source themselves. 84 | #define _CASA_BUILD_FROM_SRC 85 | 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | #include 96 | #include 97 | 98 | // json 99 | #include "cpprest/json.h" 100 | 101 | #if defined(max) 102 | #error: max macro defined -- make sure to #define NOMINMAX before including windows.h 103 | #endif 104 | #if defined(min) 105 | #error: min macro defined -- make sure to #define NOMINMAX before including windows.h 106 | #endif 107 | 108 | #if defined(__clang__) 109 | #pragma clang diagnostic pop 110 | #endif 111 | 112 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/pal/pal_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef UTILS_H 5 | #define UTILS_H 6 | 7 | #include "pal.h" 8 | 9 | #define _STRINGIFY(s) _X(s) 10 | 11 | bool ends_with(const pal::string_t& value, const pal::string_t& suffix, bool match_case); 12 | bool starts_with(const pal::string_t& value, const pal::string_t& prefix, bool match_case); 13 | pal::string_t get_executable(const pal::string_t& filename); 14 | pal::string_t get_directory(const pal::string_t& path); 15 | pal::string_t strip_file_ext(const pal::string_t& path); 16 | pal::string_t get_filename(const pal::string_t& path); 17 | pal::string_t get_filename_without_ext(const pal::string_t& path); 18 | void append_path(pal::string_t* path1, const pal::char_t* path2); 19 | bool library_exists_in_dir(const pal::string_t& lib_dir, const pal::string_t& lib_name, pal::string_t* p_lib_path); 20 | bool coreclr_exists_in_dir(const pal::string_t& candidate); 21 | void replace_char(pal::string_t* path, pal::char_t match, pal::char_t repl); 22 | const pal::char_t* get_arch(); 23 | pal::string_t get_last_known_arg( 24 | const std::unordered_map>& opts, 25 | const pal::string_t& opt_key, 26 | const pal::string_t& de_fault); 27 | bool parse_known_args( 28 | const int argc, 29 | const pal::char_t* argv[], 30 | const std::vector& known_opts, 31 | std::unordered_map>* opts, 32 | int* num_args); 33 | bool skip_utf8_bom(pal::ifstream_t* stream); 34 | #endif 35 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/pal/trace.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include "trace.h" 5 | 6 | static bool g_enabled = false; 7 | 8 | // 9 | // Turn on tracing for the corehost based on "COREHOST_TRACE" env. 10 | // 11 | void trace::setup() 12 | { 13 | // Read trace environment variable 14 | pal::string_t trace_str; 15 | if (!pal::getenv(_X("COREHOST_TRACE"), &trace_str)) 16 | { 17 | return; 18 | } 19 | 20 | auto trace_val = pal::xtoi(trace_str.c_str()); 21 | if (trace_val > 0) 22 | { 23 | trace::enable(); 24 | trace::info(_X("Tracing enabled")); 25 | } 26 | } 27 | 28 | void trace::enable() 29 | { 30 | g_enabled = true; 31 | } 32 | 33 | bool trace::is_enabled() 34 | { 35 | return g_enabled; 36 | } 37 | 38 | void trace::verbose(const pal::char_t* format, ...) 39 | { 40 | if (g_enabled) 41 | { 42 | va_list args; 43 | va_start(args, format); 44 | pal::err_vprintf(format, args); 45 | va_end(args); 46 | } 47 | } 48 | 49 | void trace::info(const pal::char_t* format, ...) 50 | { 51 | if (g_enabled) 52 | { 53 | va_list args; 54 | va_start(args, format); 55 | pal::err_vprintf(format, args); 56 | va_end(args); 57 | } 58 | } 59 | 60 | void trace::error(const pal::char_t* format, ...) 61 | { 62 | // Always print errors 63 | va_list args; 64 | va_start(args, format); 65 | pal::err_vprintf(format, args); 66 | va_end(args); 67 | } 68 | 69 | void trace::println(const pal::char_t* format, ...) 70 | { 71 | va_list args; 72 | va_start(args, format); 73 | pal::out_vprintf(format, args); 74 | va_end(args); 75 | } 76 | 77 | void trace::println() 78 | { 79 | println(_X("")); 80 | } 81 | 82 | void trace::warning(const pal::char_t* format, ...) 83 | { 84 | if (g_enabled) 85 | { 86 | va_list args; 87 | va_start(args, format); 88 | pal::err_vprintf(format, args); 89 | va_end(args); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/CoreCLREmbedding/pal/trace.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef TRACE_H 5 | #define TRACE_H 6 | 7 | #include "pal.h" 8 | 9 | namespace trace 10 | { 11 | void setup(); 12 | void enable(); 13 | bool is_enabled(); 14 | void verbose(const pal::char_t* format, ...); 15 | void info(const pal::char_t* format, ...); 16 | void warning(const pal::char_t* format, ...); 17 | void error(const pal::char_t* format, ...); 18 | void println(const pal::char_t* format, ...); 19 | void println(); 20 | }; 21 | 22 | #endif // TRACE_H 23 | -------------------------------------------------------------------------------- /src/common/callbackhelper.cpp: -------------------------------------------------------------------------------- 1 | #include "edge_common.h" 2 | 3 | // The Callback to use to force the next tick to happen 4 | Nan::Callback* CallbackHelper::tickCallback; 5 | 6 | static void NoOpFunction(const Nan::FunctionCallbackInfo& info) 7 | { 8 | // Do nothing, this is a no-op function 9 | } 10 | 11 | // Initialize the callback 12 | void CallbackHelper::Initialize() 13 | { 14 | DBG("CallbackHelper::Initialize"); 15 | 16 | tickCallback = new Nan::Callback(Nan::New(NoOpFunction, Nan::Null())); 17 | } 18 | 19 | // Make the no-op callback, forcing the next tick to execute 20 | void CallbackHelper::KickNextTick() 21 | { 22 | Nan::HandleScope scope; 23 | Nan::AsyncResource resource("CallbackHelper::KickNextTick"); 24 | tickCallback->Call(0, 0, &resource); 25 | } -------------------------------------------------------------------------------- /src/common/clrfuncreflectionwrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Reflection; 4 | 5 | public class ClrFuncReflectionWrap 6 | { 7 | Object instance; 8 | MethodInfo invokeMethod; 9 | 10 | public static ClrFuncReflectionWrap Create(Assembly assembly, String typeName, String methodName) 11 | { 12 | Type startupType = assembly.GetType(typeName); 13 | 14 | if (startupType == null) 15 | { 16 | throw new TypeLoadException("Could not load type '" + typeName + "'"); 17 | } 18 | 19 | ClrFuncReflectionWrap wrap = new ClrFuncReflectionWrap(); 20 | wrap.instance = System.Activator.CreateInstance(startupType); 21 | wrap.invokeMethod = startupType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public); 22 | if (wrap.invokeMethod == null) 23 | { 24 | throw new System.InvalidOperationException( 25 | $"Unable to access the CLR method to wrap through reflection. Make sure it is a public instance method.\r\nType: {typeName}, Method: {methodName}, Assembly: {assembly.GetName().FullName}"); 26 | } 27 | 28 | return wrap; 29 | } 30 | 31 | public Task Call(Object payload) 32 | { 33 | return (Task)this.invokeMethod.Invoke(this.instance, new object[] { payload }); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/common/edge.cpp: -------------------------------------------------------------------------------- 1 | #if !defined(HAVE_CORECLR) && !defined(HAVE_NATIVECLR) 2 | #error "CoreCLR and/or a native .NET runtime (native .NET on Windows or Mono on Linux) must be installed in order for Edge.js to compile." 3 | #endif 4 | 5 | #include "edge_common.h" 6 | 7 | #ifdef HAVE_CORECLR 8 | #include "../CoreCLREmbedding/edge.h" 9 | #endif 10 | #ifdef HAVE_NATIVECLR 11 | #ifdef EDGE_PLATFORM_WINDOWS 12 | #include "../dotnet/edge.h" 13 | #else 14 | #include "../mono/edge.h" 15 | #endif 16 | #endif 17 | 18 | BOOL debugMode; 19 | BOOL enableScriptIgnoreAttribute; 20 | BOOL enableMarshalEnumAsInt; 21 | 22 | NAN_METHOD(initializeClrFunc) 23 | { 24 | #ifdef HAVE_NATIVECLR 25 | #ifdef HAVE_CORECLR 26 | if (HasEnvironmentVariable("EDGE_USE_CORECLR")) 27 | { 28 | CoreClrFunc::Initialize(info); 29 | } 30 | 31 | #endif 32 | ClrFunc::Initialize(info); 33 | #else 34 | CoreClrFunc::Initialize(info); 35 | #endif 36 | } 37 | 38 | #ifdef EDGE_PLATFORM_WINDOWS 39 | #pragma unmanaged 40 | #endif 41 | NAN_MODULE_INIT(init) 42 | { 43 | debugMode = HasEnvironmentVariable("EDGE_DEBUG"); 44 | DBG("edge::init"); 45 | 46 | V8SynchronizationContext::Initialize(); 47 | CallbackHelper::Initialize(); 48 | 49 | #ifdef HAVE_CORECLR 50 | if (FAILED(CoreClrEmbedding::Initialize(debugMode))) 51 | { 52 | DBG("Error occurred during CoreCLR initialization"); 53 | return; 54 | } 55 | #else 56 | #ifndef EDGE_PLATFORM_WINDOWS 57 | MonoEmbedding::Initialize(); 58 | #endif 59 | #endif 60 | 61 | enableScriptIgnoreAttribute = HasEnvironmentVariable("EDGE_ENABLE_SCRIPTIGNOREATTRIBUTE"); 62 | enableMarshalEnumAsInt = HasEnvironmentVariable("EDGE_MARSHAL_ENUM_AS_INT"); 63 | Nan::Set(target, 64 | Nan::New("initializeClrFunc").ToLocalChecked(), 65 | Nan::GetFunction(Nan::New(initializeClrFunc)).ToLocalChecked()); 66 | } 67 | 68 | #ifdef EDGE_PLATFORM_WINDOWS 69 | #pragma unmanaged 70 | #endif 71 | bool HasEnvironmentVariable(const char* variableName) 72 | { 73 | #ifdef EDGE_PLATFORM_WINDOWS 74 | return 0 < GetEnvironmentVariable(variableName, NULL, 0); 75 | #else 76 | return getenv(variableName) != NULL; 77 | #endif 78 | } 79 | 80 | #ifdef EDGE_PLATFORM_WINDOWS 81 | #pragma unmanaged 82 | #endif 83 | #ifdef HAVE_CORECLR 84 | #if NODE_MAJOR_VERSION >= 10 85 | NAN_MODULE_WORKER_ENABLED(edge_coreclr, init) 86 | #else 87 | NODE_MODULE(edge_coreclr, init) 88 | #endif 89 | #else 90 | #if NODE_MAJOR_VERSION >= 10 91 | NAN_MODULE_WORKER_ENABLED(edge_nativeclr, init) 92 | #else 93 | NODE_MODULE(edge_nativeclr, init) 94 | #endif 95 | #endif 96 | // vim: ts=4 sw=4 et: 97 | -------------------------------------------------------------------------------- /src/common/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "edge_common.h" 2 | 3 | v8::Local throwV8Exception(v8::Local exception) 4 | { 5 | Nan::EscapableHandleScope scope; 6 | Nan::ThrowError(exception); 7 | return scope.Escape(exception); 8 | } 9 | 10 | v8::Local throwV8Exception(const char* format, ...) 11 | { 12 | va_list args; 13 | va_start(args, format); 14 | 15 | size_t size = vsnprintf(NULL, 0, format, args); 16 | char* message = new char[size + 1]; 17 | 18 | va_start(args, format); 19 | vsnprintf(message, size + 1, format, args); 20 | 21 | Nan::EscapableHandleScope scope; 22 | 23 | v8::Local exception = Nan::New(); 24 | exception->SetPrototype(Nan::GetCurrentContext(), v8::Exception::Error(Nan::New(message).ToLocalChecked())); 25 | 26 | v8::Local exceptionValue = exception; 27 | Nan::ThrowError(exceptionValue); 28 | 29 | return scope.Escape(exception); 30 | } 31 | -------------------------------------------------------------------------------- /src/dotnet/clractioncontext.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | void ClrActionContext::ActionCallback(void* data) 4 | { 5 | ClrActionContext* context = (ClrActionContext*)data; 6 | System::Action^ action = context->action; 7 | delete context; 8 | action(); 9 | } 10 | -------------------------------------------------------------------------------- /src/dotnet/clrfuncreflectionwrap.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | ClrFuncReflectionWrap::ClrFuncReflectionWrap() 4 | { 5 | // empty 6 | } 7 | 8 | ClrFuncReflectionWrap^ ClrFuncReflectionWrap::Create( 9 | Assembly^ assembly, System::String^ typeName, System::String^ methodName) 10 | { 11 | System::Type^ startupType = assembly->GetType(typeName, true, true); 12 | ClrFuncReflectionWrap^ wrap = gcnew ClrFuncReflectionWrap(); 13 | wrap->instance = System::Activator::CreateInstance(startupType, false); 14 | wrap->invokeMethod = startupType->GetMethod(methodName, BindingFlags::Instance | BindingFlags::Public); 15 | if (wrap->invokeMethod == nullptr) 16 | { 17 | throw gcnew System::InvalidOperationException( 18 | System::String::Format("Unable to access the CLR method to wrap through reflection. Make sure it is a public instance method.\r\nType: {0}, Method: {1}, Assembly: {2}", 19 | typeName, methodName, assembly->GetName()->FullName)); 20 | } 21 | 22 | return wrap; 23 | } 24 | 25 | System::Threading::Tasks::Task^ ClrFuncReflectionWrap::Call(System::Object^ payload) 26 | { 27 | return (System::Threading::Tasks::Task^)this->invokeMethod->Invoke( 28 | this->instance, gcnew array { payload }); 29 | } 30 | -------------------------------------------------------------------------------- /src/dotnet/nodejsfunc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Portions Copyright (c) Microsoft Corporation. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS 10 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 11 | * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR 12 | * PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 13 | * 14 | * See the Apache Version 2.0 License for specific language governing 15 | * permissions and limitations under the License. 16 | */ 17 | #include "edge.h" 18 | 19 | NodejsFunc::NodejsFunc(v8::Local function) 20 | { 21 | DBG("NodejsFunc::NodejsFunc"); 22 | this->Func = new Nan::Persistent; 23 | this->Func->Reset(function); 24 | } 25 | 26 | NodejsFunc::~NodejsFunc() 27 | { 28 | this->!NodejsFunc(); 29 | } 30 | 31 | NodejsFunc::!NodejsFunc() 32 | { 33 | DBG("NodejsFunc::!NodejsFunc"); 34 | PersistentDisposeContext^ context = gcnew PersistentDisposeContext((Nan::Persistent*)this->Func); 35 | ClrActionContext* data = new ClrActionContext; 36 | data->action = gcnew System::Action(context, &PersistentDisposeContext::CallDisposeOnV8Thread); 37 | uv_edge_async_t* uv_edge_async = V8SynchronizationContext::RegisterAction(ClrActionContext::ActionCallback, data); 38 | V8SynchronizationContext::ExecuteAction(uv_edge_async); 39 | } 40 | 41 | System::Threading::Tasks::Task^ NodejsFunc::FunctionWrapper(System::Object^ payload) 42 | { 43 | DBG("NodejsFunc::FunctionWrapper"); 44 | NodejsFuncInvokeContext^ context = gcnew NodejsFuncInvokeContext(this, payload); 45 | ClrActionContext* data = new ClrActionContext; 46 | data->action = gcnew System::Action(context, &NodejsFuncInvokeContext::CallFuncOnV8Thread); 47 | uv_edge_async_t* uv_edge_async = V8SynchronizationContext::RegisterAction(ClrActionContext::ActionCallback, data); 48 | V8SynchronizationContext::ExecuteAction(uv_edge_async); 49 | 50 | return context->TaskCompletionSource->Task; 51 | } 52 | -------------------------------------------------------------------------------- /src/dotnet/persistentdisposecontext.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS 10 | * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 11 | * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR 12 | * PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 13 | * 14 | * See the Apache Version 2.0 License for specific language governing 15 | * permissions and limitations under the License. 16 | */ 17 | #include "edge.h" 18 | 19 | PersistentDisposeContext::PersistentDisposeContext(Nan::Persistent* handle) 20 | : ptr((void*)handle) 21 | { 22 | DBG("PersistentDisposeContext::PersistentDisposeContext"); 23 | } 24 | 25 | void PersistentDisposeContext::CallDisposeOnV8Thread() { 26 | DBG("PersistentDisposeContext::CallDisposeOnV8Thread"); 27 | 28 | Nan::Persistent* handle = (Nan::Persistent*)ptr.ToPointer(); 29 | handle->Reset(); 30 | delete handle; 31 | } -------------------------------------------------------------------------------- /src/dotnet/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | v8::Local stringCLR2V8(System::String^ text) 4 | { 5 | Nan::EscapableHandleScope scope; 6 | if (text->Length > 0) 7 | { 8 | array^ utf8 = System::Text::Encoding::UTF8->GetBytes(text); 9 | pin_ptr ch = &utf8[0]; 10 | return scope.Escape(Nan::New((char*)ch, utf8->Length).ToLocalChecked()); 11 | } 12 | else 13 | { 14 | return scope.Escape(Nan::New("").ToLocalChecked()); 15 | } 16 | } 17 | 18 | System::String^ stringV82CLR(v8::Local text) 19 | { 20 | Nan::HandleScope scope; 21 | Nan::Utf8String utf8text(text); 22 | if (*utf8text) 23 | { 24 | return gcnew System::String( 25 | *utf8text, 0, utf8text.length(), System::Text::Encoding::UTF8); 26 | } 27 | else 28 | { 29 | return System::String::Empty; 30 | } 31 | } 32 | 33 | System::String^ stringV82CLR(Nan::Utf8String& utf8text) 34 | { 35 | Nan::HandleScope scope; 36 | if (*utf8text) 37 | { 38 | return gcnew System::String( 39 | *utf8text, 0, utf8text.length(), System::Text::Encoding::UTF8); 40 | } 41 | else 42 | { 43 | return System::String::Empty; 44 | } 45 | } 46 | System::String^ exceptionV82stringCLR(v8::Local exception) 47 | { 48 | v8::Isolate *isolate = v8::Isolate::GetCurrent(); 49 | v8::Local context = isolate->GetCurrentContext(); 50 | Nan::HandleScope scope; 51 | if (exception->IsObject()) 52 | { 53 | v8::Local stack = exception->ToObject(context).ToLocalChecked()->Get(Nan::GetCurrentContext(), Nan::New("stack").ToLocalChecked()).ToLocalChecked(); 54 | if (stack->IsString()) 55 | { 56 | return gcnew System::String(stringV82CLR(stack->ToString(context).ToLocalChecked())); 57 | } 58 | } 59 | 60 | return gcnew System::String(stringV82CLR(v8::Local::Cast(exception))); 61 | } 62 | -------------------------------------------------------------------------------- /src/double/Edge.js/Edge.js.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | With Edge.js you can script Node.js in a .NET application. Edge.js allows you to run Node.js and .NET code in one process. You can call Node.js functions from .NET and .NET functions from Node.js. Edge.js takes care of marshalling data between CLR and V8. Edge.js also reconciles threading models of single threaded V8 and multi-threaded CLR. Edge.js ensures correct lifetime of objects on V8 and CLR heaps. This Edge.js NuGet package supports scripting Node.js v6.5.0. 4 | Copyright 2015 Tomasz Janczuk 5 | 9.3.0 6 | net462;net6.0; 7 | EdgeJs 8 | Edge.js 9 | node.js;node;.net;edge;edge.js;v8;clr;coreclr;mono;interop;javascript 10 | https://raw.githubusercontent.com/agracio/edge-js/master/LICENSE 11 | false 12 | 13 | 14 | 15 | content/edge/x64/ 16 | true 17 | 18 | 19 | content/edge/x86/ 20 | true 21 | 22 | 23 | content/edge/ 24 | true 25 | 26 | 27 | tools/ 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | true 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/double/Edge.js/dotnetcore/nodejsfunc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Runtime.CompilerServices; 4 | 5 | public class NodejsFunc 6 | { 7 | public IntPtr Context 8 | { 9 | get; 10 | private set; 11 | } 12 | 13 | public NodejsFunc(IntPtr context) 14 | { 15 | Context = context; 16 | } 17 | 18 | ~NodejsFunc() 19 | { 20 | // TODO: implement release 21 | } 22 | 23 | public Func> GetFunc() 24 | { 25 | return new Func>(FunctionWrapper); 26 | } 27 | 28 | private Task FunctionWrapper(object payload) 29 | { 30 | CoreCLREmbedding.DebugMessage("NodejsFunc::FunctionWrapper (CLR) - Started"); 31 | 32 | NodejsFuncInvokeContext invokeContext = new NodejsFuncInvokeContext(this, payload); 33 | invokeContext.CallFunc(); 34 | 35 | CoreCLREmbedding.DebugMessage("NodejsFunc::FunctionWrapper (CLR) - Node.js function invoked on the V8 thread, returning the task completion source"); 36 | 37 | return invokeContext.TaskCompletionSource.Task; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/double/Edge.js/dotnetcore/nodejsfuncinvokecontext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | public delegate void NodejsFuncCompleteDelegate(IntPtr context, int taskStatus, IntPtr result, int resultType); 7 | 8 | public class NodejsFuncInvokeContext 9 | { 10 | private NodejsFunc functionContext; 11 | private object payload; 12 | private static IntPtr NodejsFuncCompleteCallback; 13 | private static NodejsFuncCompleteDelegate NodeJsFuncCompleteInstance; 14 | 15 | static NodejsFuncInvokeContext() 16 | { 17 | NodeJsFuncCompleteInstance = new NodejsFuncCompleteDelegate(NodejsFuncComplete); 18 | NodejsFuncCompleteCallback = Marshal.GetFunctionPointerForDelegate(NodeJsFuncCompleteInstance); 19 | } 20 | 21 | internal static CallV8FunctionDelegate CallV8Function 22 | { 23 | get; 24 | set; 25 | } 26 | 27 | public TaskCompletionSource TaskCompletionSource 28 | { 29 | get; 30 | private set; 31 | } 32 | 33 | public NodejsFuncInvokeContext(NodejsFunc functionContext, object payload) 34 | { 35 | this.functionContext = functionContext; 36 | this.payload = payload; 37 | this.TaskCompletionSource = new TaskCompletionSource(); 38 | } 39 | 40 | internal void CallFunc() 41 | { 42 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::CallFunc (CLR) - Starting"); 43 | 44 | V8Type v8PayloadType; 45 | IntPtr v8Payload = CoreCLREmbedding.MarshalCLRToV8(payload, out v8PayloadType); 46 | 47 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::CallFunc (CLR) - Marshalled payload data for V8"); 48 | 49 | IntPtr callbackContext = GCHandle.ToIntPtr(GCHandle.Alloc(this)); 50 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::CallFunc (CLR) - Getting a GCHandle for this context object"); 51 | 52 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::CallFunc (CLR) - Invoking the unmanaged V8 function to invoke the Node.js function on the V8 thread"); 53 | CallV8Function(v8Payload, (int)v8PayloadType, functionContext.Context, callbackContext, NodejsFuncCompleteCallback); 54 | } 55 | 56 | public static void NodejsFuncComplete(IntPtr context, int taskStatus, IntPtr result, int resultType) 57 | { 58 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::NodejsFuncComplete (CLR) - Starting"); 59 | 60 | GCHandle gcHandle = GCHandle.FromIntPtr(context); 61 | NodejsFuncInvokeContext actualContext = (NodejsFuncInvokeContext)gcHandle.Target; 62 | 63 | gcHandle.Free(); 64 | 65 | V8Type v8ResultType = (V8Type)resultType; 66 | object marshalledResult = CoreCLREmbedding.MarshalV8ToCLR(result, v8ResultType); 67 | 68 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::NodejsFuncComplete (CLR) - Marshalled result data back to the CLR"); 69 | 70 | if (taskStatus == (int)TaskStatus.Faulted) 71 | { 72 | actualContext.TaskCompletionSource.SetException((Exception)marshalledResult); 73 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::NodejsFuncComplete (CLR) - Set the exception received from Node.js: {0}", ((Exception)marshalledResult).Message); 74 | } 75 | 76 | else 77 | { 78 | actualContext.TaskCompletionSource.SetResult(marshalledResult); 79 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::NodejsFuncComplete (CLR) - Set result data"); 80 | } 81 | 82 | CoreCLREmbedding.DebugMessage("NodejsFuncInvokeContext::NodejsFuncComplete (CLR) - Finished"); 83 | } 84 | } -------------------------------------------------------------------------------- /src/mono/clractioncontext.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | void ClrActionContext::ActionCallback(void* data) 4 | { 5 | static MonoMethod* actionInvoke; 6 | if (!actionInvoke) 7 | { 8 | MonoClass* actionClass = mono_class_from_name(mono_get_corlib(), "System", "Action"); 9 | actionInvoke = mono_class_get_method_from_name(actionClass, "Invoke", -1); 10 | } 11 | 12 | ClrActionContext* context = (ClrActionContext*)data; 13 | MonoObject* action = mono_gchandle_get_target(context->action); 14 | MonoException* exc = NULL; 15 | mono_runtime_invoke(actionInvoke, action, NULL, (MonoObject**)&exc); 16 | mono_gchandle_free(context->action); 17 | delete context; 18 | if (exc) 19 | ABORT_TODO(); 20 | } 21 | -------------------------------------------------------------------------------- /src/mono/clrfuncinvokecontext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Runtime.CompilerServices; 4 | 5 | class ClrFuncInvokeContext 6 | { 7 | #pragma warning disable 649 // assigned from clrfuncinvokecontext.cpp through embedding APIs 8 | IntPtr native; 9 | #pragma warning disable 169 // assigned from clrfuncinvokecontext.cpp through embedding APIs 10 | Object Payload; 11 | Task Task; 12 | bool Sync; 13 | #pragma warning restore 169 14 | #pragma warning restore 649 15 | 16 | [MethodImplAttribute(MethodImplOptions.InternalCall)] 17 | static extern void CompleteOnCLRThreadICall(IntPtr ptr, Task task); 18 | 19 | internal void CompleteOnCLRThread(Task task) 20 | { 21 | CompleteOnCLRThreadICall(native, task); 22 | } 23 | 24 | [MethodImplAttribute(MethodImplOptions.InternalCall)] 25 | static extern void CompleteOnV8ThreadAsynchronousICall(IntPtr ptr); 26 | 27 | void CompleteOnV8ThreadAsynchronous() 28 | { 29 | CompleteOnV8ThreadAsynchronousICall(native); 30 | } 31 | 32 | public Action GetCompleteOnV8ThreadAsynchronousAction() 33 | { 34 | return new Action(CompleteOnV8ThreadAsynchronous); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /src/mono/dictionary.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | //void Dictionary::Add(MonoObject* _this, const char* name, MonoObject* value) 4 | //{ 5 | // static MonoMethod* add; 6 | // 7 | // if(!add) { 8 | // add = mono_class_get_method_from_name(mono_object_get_class(_this), 9 | // "System.Collections.Generic.IDictionary.Add", -1); 10 | // } 11 | // 12 | // void* params[2]; 13 | // params[0] = mono_string_new(mono_domain_get(), name); 14 | // params[1] = value; 15 | // 16 | // mono_runtime_invoke(add, _this, params, NULL); 17 | //} 18 | 19 | void Dictionary::Add(MonoObject* _this, const char* name, MonoObject* value) 20 | { 21 | static MonoMethod* add; 22 | 23 | if(!add) { 24 | add = mono_class_get_method_from_name(MonoEmbedding::GetClass(), "AddPropertyToObject", -1); 25 | } 26 | 27 | void* params[3]; 28 | params[0] = _this; //dict 29 | params[1] = mono_string_new(mono_domain_get(), name); // key 30 | params[2] = value; // value 31 | 32 | mono_runtime_invoke(add, _this, params, NULL); 33 | } 34 | -------------------------------------------------------------------------------- /src/mono/nodejsfunc.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | static MonoClass* GetNodejsFuncClass() 4 | { 5 | static MonoClass* klass; 6 | 7 | if (!klass) 8 | klass = mono_class_from_name(MonoEmbedding::GetImage(), "", "NodejsFunc"); 9 | 10 | return klass; 11 | } 12 | 13 | NodejsFunc::NodejsFunc(v8::Local function) 14 | { 15 | DBG("NodejsFunc::NodejsFunc"); 16 | 17 | static MonoMethod* ctor; 18 | if (!ctor) 19 | ctor = mono_class_get_method_from_name(GetNodejsFuncClass(), ".ctor", -1); 20 | 21 | this->Func = new Nan::Persistent; 22 | (this->Func)->Reset(function); 23 | 24 | MonoObject* thisObj = mono_object_new(mono_domain_get(), GetNodejsFuncClass()); 25 | MonoException* exc = NULL; 26 | void *thisPtr = this; 27 | void *args[] = { &thisPtr }; 28 | mono_runtime_invoke(ctor, thisObj, args, (MonoObject**)&exc); 29 | _this = mono_gchandle_new_weakref(thisObj, FALSE); 30 | } 31 | 32 | NodejsFunc::~NodejsFunc() 33 | { 34 | DBG("NodejsFunc::~NodejsFunc"); 35 | this->Func->Reset(); 36 | delete this->Func; 37 | this->Func = NULL; 38 | } 39 | 40 | void NodejsFunc::Release(NodejsFunc* _this) 41 | { 42 | delete _this; 43 | } 44 | 45 | MonoObject* NodejsFunc::GetFunc() 46 | { 47 | static MonoMethod* method; 48 | 49 | if (!method) 50 | method = mono_class_get_method_from_name(GetNodejsFuncClass(), "GetFunc", -1); 51 | 52 | MonoException* exc = NULL; 53 | MonoObject* func = mono_runtime_invoke(method, mono_gchandle_get_target(_this), NULL, (MonoObject**)&exc); 54 | 55 | return func; 56 | } 57 | 58 | void NodejsFunc::ExecuteActionOnV8Thread(MonoObject* action) 59 | { 60 | ClrActionContext* data = new ClrActionContext; 61 | data->action = mono_gchandle_new(action, FALSE); // released in ClrActionContext::ActionCallback 62 | uv_edge_async_t* uv_edge_async = V8SynchronizationContext::RegisterAction(ClrActionContext::ActionCallback, data); 63 | V8SynchronizationContext::ExecuteAction(uv_edge_async); 64 | } 65 | -------------------------------------------------------------------------------- /src/mono/nodejsfunc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Runtime.CompilerServices; 4 | 5 | class NodejsFunc 6 | { 7 | public IntPtr NativeNodejsFunc { get; set; } 8 | 9 | public NodejsFunc(IntPtr native) 10 | { 11 | this.NativeNodejsFunc = native; 12 | } 13 | 14 | ~NodejsFunc() 15 | { 16 | IntPtr native = this.NativeNodejsFunc; 17 | ExecuteActionOnV8Thread(() => { 18 | Release(native); 19 | }); 20 | } 21 | 22 | [MethodImplAttribute(MethodImplOptions.InternalCall)] 23 | static extern void Release(IntPtr nativeNodejsFunc); 24 | 25 | Func> GetFunc() 26 | { 27 | return new Func>(this.FunctionWrapper); 28 | } 29 | 30 | Task FunctionWrapper(object payload) 31 | { 32 | NodejsFuncInvokeContext ctx = new NodejsFuncInvokeContext(this, payload); 33 | ExecuteActionOnV8Thread(ctx.CallFuncOnV8Thread); 34 | 35 | return ctx.TaskCompletionSource.Task; 36 | } 37 | 38 | [MethodImplAttribute(MethodImplOptions.InternalCall)] 39 | static extern void ExecuteActionOnV8Thread(Action action); 40 | }; 41 | -------------------------------------------------------------------------------- /src/mono/nodejsfuncinvokecontext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Runtime.CompilerServices; 4 | 5 | class NodejsFuncInvokeContext { 6 | NodejsFunc functionContext; 7 | object payload; 8 | 9 | public TaskCompletionSource TaskCompletionSource { get; set; } 10 | 11 | public NodejsFuncInvokeContext(NodejsFunc functionContext, object payload) 12 | { 13 | this.functionContext = functionContext; 14 | this.payload = payload; 15 | this.TaskCompletionSource = new TaskCompletionSource(); 16 | } 17 | 18 | public void CallFuncOnV8Thread() 19 | { 20 | // This function must run on V8 thread 21 | CallFuncOnV8ThreadInternal( 22 | this, this.functionContext.NativeNodejsFunc, this.payload); 23 | } 24 | 25 | [MethodImplAttribute(MethodImplOptions.InternalCall)] 26 | static extern void CallFuncOnV8ThreadInternal(NodejsFuncInvokeContext _this, IntPtr nativeNodejsFunc, object payload); 27 | 28 | public void Complete(object exception, object result) 29 | { 30 | Task.Run(() => { 31 | if (exception != null) 32 | { 33 | var e = exception as Exception; 34 | var s = exception as string; 35 | if (e != null) 36 | { 37 | this.TaskCompletionSource.SetException(e); 38 | } 39 | else if (!string.IsNullOrEmpty(s)) 40 | { 41 | this.TaskCompletionSource.SetException(new Exception(s)); 42 | } 43 | else 44 | { 45 | this.TaskCompletionSource.SetException( 46 | new InvalidOperationException("Unrecognized exception received from JavaScript.")); 47 | } 48 | } 49 | else 50 | { 51 | this.TaskCompletionSource.SetResult(result); 52 | } 53 | }); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /src/mono/task.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | TaskStatus SystemThreading::Task::Status(MonoObject* _this) 4 | { 5 | MonoProperty* prop = mono_class_get_property_from_name(mono_object_get_class(_this), "Status"); 6 | MonoObject* statusBoxed = mono_property_get_value(prop, _this, NULL, NULL); 7 | TaskStatus status = *(TaskStatus*)mono_object_unbox(statusBoxed); 8 | return status; 9 | } 10 | 11 | MonoException* SystemThreading::Task::Exception(MonoObject* _this) 12 | { 13 | MonoProperty* prop = mono_class_get_property_from_name(mono_object_get_class(_this), "Exception"); 14 | MonoObject* exception = mono_property_get_value(prop, _this, NULL, NULL); 15 | return (MonoException*)exception; 16 | } 17 | 18 | MonoObject* SystemThreading::Task::Result(MonoObject* _this) 19 | { 20 | MonoProperty* prop = mono_class_get_property_from_name(mono_object_get_class(_this), "Result"); 21 | MonoObject* result = mono_property_get_value(prop, _this, NULL, NULL); 22 | return result; 23 | } 24 | -------------------------------------------------------------------------------- /src/mono/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "edge.h" 2 | 3 | v8::Local stringCLR2V8(MonoString* text) 4 | { 5 | Nan::EscapableHandleScope scope; 6 | return scope.Escape(Nan::New( 7 | mono_string_chars(text), 8 | mono_string_length(text)).ToLocalChecked()); 9 | } 10 | 11 | MonoString* stringV82CLR(v8::Local text) 12 | { 13 | Nan::HandleScope scope; 14 | Nan::Utf8String utf8text(text); 15 | return mono_string_new(mono_domain_get(), *utf8text); 16 | } 17 | 18 | MonoString* exceptionV82stringCLR(v8::Local exception) 19 | { 20 | v8::Isolate *isolate = v8::Isolate::GetCurrent(); 21 | v8::Local context = isolate->GetCurrentContext(); 22 | Nan::HandleScope scope; 23 | if (exception->IsObject()) 24 | { 25 | v8::Local stack = exception->ToObject(Nan::GetCurrentContext()).ToLocalChecked()->Get(Nan::GetCurrentContext(), Nan::New("stack").ToLocalChecked()).ToLocalChecked(); 26 | if (stack->IsString()) 27 | { 28 | return stringV82CLR(stack->ToString(context).ToLocalChecked()); 29 | } 30 | } 31 | 32 | return stringV82CLR(v8::Local::Cast(exception)); 33 | } 34 | -------------------------------------------------------------------------------- /test/101_edge_func.js: -------------------------------------------------------------------------------- 1 | var edge = require('../lib/edge.js'), assert = require('assert') 2 | , path = require('path'); 3 | 4 | var edgeTestDll = process.env.EDGE_USE_CORECLR ? 'test' : path.join(__dirname, 'Edge.Tests.dll'); 5 | var prefix = process.env.EDGE_USE_CORECLR ? '[CoreCLR]' : process.platform === 'win32' ? '[.NET]' : '[Mono]'; 6 | 7 | describe('edge.func', function () { 8 | 9 | it(prefix + ' exists', function () { 10 | assert.equal(typeof edge.func, 'function'); 11 | }); 12 | 13 | it(prefix + ' fails without parameters', function () { 14 | assert.throws( 15 | edge.func, 16 | /Specify the source code as string or provide an options object/ 17 | ); 18 | }); 19 | 20 | it(prefix + ' fails with a wrong parameter', function () { 21 | assert.throws( 22 | function () { edge.func(12); }, 23 | /Specify the source code as string or provide an options object/ 24 | ); 25 | }); 26 | 27 | it(prefix + ' fails with a wrong language parameter', function () { 28 | assert.throws( 29 | function () { edge.func(12, 'somescript'); }, 30 | /The first argument must be a string identifying the language compiler to use/ 31 | ); 32 | }); 33 | 34 | it(prefix + ' fails with a unsupported language parameter', function () { 35 | assert.throws( 36 | function () { edge.func('idontexist', 'somescript'); }, 37 | /Unsupported language 'idontexist'/ 38 | ); 39 | }); 40 | 41 | it(prefix + ' fails with missing assemblyFile or source', function () { 42 | assert.throws( 43 | function () { edge.func({}); }, 44 | /Provide DLL or source file name or .NET script literal as a string parameter, or specify an options object/ 45 | ); 46 | }); 47 | 48 | it(prefix + ' fails with both assemblyFile or source', function () { 49 | assert.throws( 50 | function () { edge.func({ assemblyFile: 'foo.dll', source: 'async (input) => { return null; }'}); }, 51 | /Provide either an asseblyFile or source property, but not both/ 52 | ); 53 | }); 54 | 55 | it(prefix + ' fails with nonexisting assemblyFile', function () { 56 | assert.throws( 57 | function () { edge.func('idontexist.dll'); }, 58 | /System.IO.FileNotFoundException/ 59 | ); 60 | }); 61 | 62 | it(prefix + ' succeeds with assemblyFile as string', function () { 63 | if (process.env.EDGE_USE_CORECLR) { 64 | this.skip(); 65 | } 66 | var func = edge.func(edgeTestDll); 67 | assert.equal(typeof func, 'function'); 68 | }); 69 | 70 | it(prefix + ' succeeds with assemblyFile as options property', function () { 71 | if (process.env.EDGE_USE_CORECLR) { 72 | this.skip(); 73 | } 74 | var func = edge.func({ assemblyFile: edgeTestDll }); 75 | assert.equal(typeof func, 'function'); 76 | }); 77 | 78 | it(prefix + ' succeeds with assemblyFile and type name', function () { 79 | var func = edge.func({ 80 | assemblyFile: edgeTestDll, 81 | typeName: 'Edge.Tests.Startup' 82 | }); 83 | assert.equal(typeof func, 'function'); 84 | }); 85 | 86 | it(prefix + ' fails with assemblyFile and nonexisting type name', function () { 87 | assert.throws( 88 | function () { 89 | edge.func({ 90 | assemblyFile: edgeTestDll, 91 | typeName: 'Edge.Tests.idontexist' 92 | }); 93 | }, 94 | /Could not load type 'Edge.Tests.idontexist'/ 95 | ); 96 | }); 97 | 98 | it(prefix + ' succeeds with assemblyFile, type name, and method name', function () { 99 | var func = edge.func({ 100 | assemblyFile: edgeTestDll, 101 | typeName: 'Edge.Tests.Startup', 102 | methodName: 'Invoke' 103 | }); 104 | assert.equal(typeof func, 'function'); 105 | }); 106 | 107 | it(prefix + ' fails with assemblyFile, type name and nonexisting method name', function () { 108 | assert.throws( 109 | function () { 110 | edge.func({ 111 | assemblyFile: edgeTestDll, 112 | typeName: 'Edge.Tests.Startup', 113 | methodName: 'idontexist' 114 | }); 115 | }, 116 | /Unable to access the CLR method to wrap through reflection/ 117 | ); 118 | }); 119 | }); -------------------------------------------------------------------------------- /test/202_serialization.js: -------------------------------------------------------------------------------- 1 | var edge = require('../lib/edge.js'), assert = require('assert'), path = require('path'); 2 | 3 | var prefix = process.env.EDGE_USE_CORECLR ? '[CoreCLR]' : process.platform === 'win32' ? '[.NET]' : '[Mono]'; 4 | 5 | describe('serialization', function () { 6 | 7 | it(prefix + ' complex exception serialization', function (done) { 8 | if (process.env.EDGE_USE_CORECLR || process.platform !== 'win32') { 9 | this.skip(); 10 | } 11 | var func = edge.func({ 12 | source: function () {/* 13 | #r "System.Data.dll" 14 | 15 | using System.Data; 16 | using System.Data.SqlClient; 17 | 18 | async (input) => 19 | { 20 | 21 | using (SqlConnection connection = new SqlConnection("Data Source=my_localhost;Initial Catalog=catalog;Integrated Security=True;Connection Timeout=1")) 22 | { 23 | connection.Open(); 24 | } 25 | return input.ToString(); 26 | 27 | } 28 | */ 29 | } 30 | }); 31 | func("JavaScript", function (error, result) { 32 | var exception = error.toString(); 33 | var contains = exception.indexOf('A network-related or instance-specific error occurred while establishing a connection to SQL Server') !== -1 34 | || exception.indexOf('Server does not exist or connection refused') !== -1 35 | || exception.indexOf('System.Data.SqlClient.SqlException') !== -1; 36 | assert.ok(contains); 37 | 38 | done(); 39 | }); 40 | 41 | 42 | }); 43 | 44 | 45 | }); -------------------------------------------------------------------------------- /test/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "reporterEnabled": "mochawesome", 3 | "mochawesomeReporterOptions": { 4 | "reportDir": "./test/mochawesome-report", 5 | "json": true, 6 | "html": false, 7 | "reportFilename": "mochawesome-{id}.json" 8 | } 9 | } -------------------------------------------------------------------------------- /test/configCI.json: -------------------------------------------------------------------------------- 1 | { 2 | "reporterEnabled": "mochawesome, mocha-junit-reporter", 3 | "mochawesomeReporterOptions": { 4 | "reportDir": "mochawesome-report", 5 | "json": true, 6 | "html": false, 7 | "reportFilename": "mochawesome-{id}.html" 8 | 9 | }, 10 | "mochaJunitReporterReporterOptions": { 11 | "mochaFile": "test-results-{id}.xml", 12 | "rootSuiteTitle": "", 13 | "includePending": true, 14 | "jenkinsMode": true, 15 | "outputs": true 16 | } 17 | } -------------------------------------------------------------------------------- /test/double/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | packages/ 3 | edge/ 4 | TestResults/ -------------------------------------------------------------------------------- /test/double/double_stress/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/double/double_stress/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("double_stress")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("double_stress")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("806b8070-743b-46f3-8178-5c1acd7badaf")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /test/double/double_stress/double_stress.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {51C38DFE-9FC5-4A14-A046-1F6EA3910904} 8 | Exe 9 | Properties 10 | double_stress 11 | double_stress 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | packages\Edge.js.7.10.1\lib\net40\EdgeJs.dll 37 | True 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | PreserveNewest 58 | 59 | 60 | 61 | 62 | 63 | PreserveNewest 64 | 65 | 66 | PreserveNewest 67 | 68 | 69 | PreserveNewest 70 | 71 | 72 | PreserveNewest 73 | 74 | 75 | 76 | 83 | -------------------------------------------------------------------------------- /test/double/double_stress/double_stress.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "double_stress", "double_stress.csproj", "{51C38DFE-9FC5-4A14-A046-1F6EA3910904}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {51C38DFE-9FC5-4A14-A046-1F6EA3910904}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {51C38DFE-9FC5-4A14-A046-1F6EA3910904}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {51C38DFE-9FC5-4A14-A046-1F6EA3910904}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {51C38DFE-9FC5-4A14-A046-1F6EA3910904}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /test/double/double_stress/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /test/double/double_test/double_test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net462 5 | enable 6 | enable 7 | default 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/double/double_test/double_test.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "double_test", "double_test.csproj", "{721FC9B2-4747-48E7-B57D-1084FCE6D7D3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {721FC9B2-4747-48E7-B57D-1084FCE6D7D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {721FC9B2-4747-48E7-B57D-1084FCE6D7D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {721FC9B2-4747-48E7-B57D-1084FCE6D7D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {721FC9B2-4747-48E7-B57D-1084FCE6D7D3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /test/hello_class.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | public class Startup 5 | { 6 | public async Task Invoke(object input) 7 | { 8 | return "Hello, " + input.ToString(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/hello_class.csx: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | public class Startup 5 | { 6 | public async Task Invoke(object input) 7 | { 8 | return "Hello, " + input.ToString(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/hello_lambda.csx: -------------------------------------------------------------------------------- 1 | async (input) => { return "Hello, " + input.ToString(); } 2 | -------------------------------------------------------------------------------- /test/test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | true 6 | true 7 | test 8 | Exe 9 | test 10 | default 11 | disable 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /tools/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set SELF=%~dp0 3 | if "%1" equ "" ( 4 | echo Usage: build.bat debug^|release {version} 5 | echo e.g. build.bat release 20.12.2 6 | echo e.g. build.bat release 20 7 | exit /b -1 8 | ) 9 | rmdir /S /Q ..\build\ 10 | 11 | for /F "delims=." %%a in ("%2") do set MAJORVERSION=%%a 12 | set MAJORVERSION=%MAJORVERSION: =% 13 | 14 | SET FLAVOR=%1 15 | if "%FLAVOR%" equ "" set FLAVOR=release 16 | 17 | shift 18 | 19 | SET DESTDIRROOT=%SELF%\..\lib\native\win32 20 | 21 | set VERSION=%1 22 | 23 | call :node_version 24 | 25 | pushd %SELF%\.. 26 | 27 | if %MAJORVERSION% LSS 23 ( 28 | call :build ia32 ia32 %VERSION% 29 | call :stamp_version 30 | call :copy 31 | if %ERRORLEVEL% neq 0 exit /b -1 32 | ) 33 | 34 | call :build x64 x64 %VERSION% 35 | call :stamp_version 36 | call :copy 37 | if %ERRORLEVEL% neq 0 exit /b -1 38 | 39 | if %MAJORVERSION% GEQ 20 ( 40 | call :build arm64 arm64 %VERSION% 41 | call :stamp_version 42 | call :copy 43 | if %ERRORLEVEL% neq 0 exit /b -1 44 | ) 45 | 46 | popd 47 | 48 | exit /b 0 49 | 50 | @REM =================================================================================== 51 | :node_version 52 | 53 | if %MAJORVERSION% equ %VERSION% ( 54 | echo Getting latest version of Node.js v%VERSION% 55 | FOR /F "tokens=* USEBACKQ" %%F IN (`node "%SELF%\getVersion.js" "%VERSION%"`) DO (SET VERSION=%%F) 56 | ) 57 | 58 | if %MAJORVERSION% equ %VERSION% ( 59 | echo Cannot determine Node.js version for %VERSION% 60 | exit /b -1 61 | ) 62 | 63 | exit /b 0 64 | 65 | @REM =================================================================================== 66 | :build 67 | 68 | SET ARCH=%2 69 | set DESTDIR=%DESTDIRROOT%\%1\%MAJORVERSION% 70 | if not exist "%DESTDIR%" mkdir "%DESTDIR%" 71 | 72 | echo Building edge.node %FLAVOR% for node.js %2 v%3 73 | 74 | FOR /F "tokens=* USEBACKQ" %%F IN (`npm config get prefix`) DO (SET NODEBASE=%%F) 75 | set GYP=%NODEBASE%\node_modules\node-gyp\bin\node-gyp.js 76 | echo %GYP% 77 | 78 | if not exist "%GYP%" ( 79 | echo Cannot find node-gyp at %GYP%. Make sure to install with npm install node-gyp -g 80 | exit /b -1 81 | ) 82 | 83 | node "%GYP%" configure --msvs_version=2022 -%FLAVOR% --target=%3 --runtime=node --arch=%2 84 | if %ERRORLEVEL% neq 0 ( 85 | echo Error configuring edge.node %FLAVOR% for node.js %2 v%3 86 | exit /b -1 87 | ) 88 | 89 | @REM Conflict when building arm64 binaries 90 | if "%2" == "arm64" ( 91 | FOR %%F IN (build\*.vcxproj) DO ( 92 | echo Patch /fp:strict in %%F 93 | powershell -Command "(Get-Content -Raw %%F) -replace 'Strict', '' | Out-File -Encoding Utf8 %%F" 94 | ) 95 | ) 96 | 97 | node "%GYP%" build 98 | 99 | exit /b 0 100 | 101 | @REM =================================================================================== 102 | :stamp_version 103 | 104 | type NUL > %DESTDIR%\node.version 105 | echo %VERSION%> %DESTDIR%\node.version 106 | 107 | exit /b 0 108 | 109 | @REM =================================================================================== 110 | :copy 111 | 112 | echo %DESTDIR% 113 | copy /y .\build\%FLAVOR%\edge_*.node "%DESTDIR%" 114 | if %ERRORLEVEL% neq 0 ( 115 | echo Error copying edge.node %FLAVOR% for node.js %ARCH% v%VERSION% 116 | exit /b -1 117 | ) 118 | rmdir /S /Q .\build\ 119 | copy /y "%DESTDIR%\..\*.dll" "%DESTDIR%" 120 | if %ERRORLEVEL% neq 0 ( 121 | echo Error copying VC redist %FLAVOR% to %DESTDIR% 122 | exit /b -1 123 | ) 124 | 125 | echo Success building edge.node %FLAVOR% for node.js %ARCH% v%VERSION% 126 | 127 | exit /b 0 128 | -------------------------------------------------------------------------------- /tools/checkMono.js: -------------------------------------------------------------------------------- 1 | const { execSync } = require('child_process'); 2 | 3 | function exists(cmd){ 4 | try{ 5 | let result = execSync(cmd).toString(); 6 | return result.toLowerCase().includes('not found') || result.length === 0 ? false : true; 7 | } 8 | catch{ 9 | return false; 10 | } 11 | } 12 | 13 | module.exports = function() { 14 | let mono = exists('which mono'); 15 | let pkgconfig = exists('which pkg-config'); 16 | return mono && pkgconfig 17 | } -------------------------------------------------------------------------------- /tools/checkplatform.js: -------------------------------------------------------------------------------- 1 | try { 2 | require('../lib/edge.js'); 3 | } 4 | catch (e) { 5 | console.log('***************************************'); 6 | console.log(e); 7 | console.log('***************************************'); 8 | } 9 | 10 | console.log('Success: platform check for edge.js: ' + process.platform + '-' + process.arch + ' v' + process.versions.node); 11 | -------------------------------------------------------------------------------- /tools/download.js: -------------------------------------------------------------------------------- 1 | var {http} = require('follow-redirects'); 2 | 3 | var urls; 4 | if (process.argv[2] === 'x86') { 5 | urls = [ 6 | 'http://nodejs.org/dist/v' + process.argv[3] + '/win-x86/node.exe' 7 | ]; 8 | } 9 | else if (process.argv[2] === 'x64') { 10 | urls = [ 11 | 'http://nodejs.org/dist/v' + process.argv[3] + '/win-x64/node.exe' 12 | ]; 13 | } 14 | else if (process.argv[2] === 'arm64') { 15 | urls = [ 16 | 'http://nodejs.org/dist/v' + process.argv[3] + '/win-arm64/node.exe' 17 | ]; 18 | } 19 | 20 | try_get(0); 21 | 22 | function try_get(i) { 23 | console.log('Trying download from', urls[i]); 24 | http.get(urls[i], function (res) { 25 | console.log('HTTP', res.statusCode); 26 | if (res.statusCode !== 200) { 27 | if (++i === urls.length) 28 | throw new Error('Unable to download node.exe'); 29 | else 30 | try_get(i); 31 | } 32 | 33 | var stream = require('fs').createWriteStream(process.argv[4] + '/node.exe'); 34 | res.pipe(stream); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /tools/download_double.js: -------------------------------------------------------------------------------- 1 | var {http} = require('follow-redirects'); 2 | 3 | 4 | console.log('Trying download from', process.argv[2]); 5 | http.get(process.argv[2], function (res) { 6 | console.log('HTTP', res.statusCode); 7 | if (res.statusCode !== 200) { 8 | throw new Error(`Unable to download ${process.argv[2]}`); 9 | } 10 | 11 | var stream = require('fs').createWriteStream(process.argv[3]); 12 | res.pipe(stream); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /tools/getVersion.js: -------------------------------------------------------------------------------- 1 | var {http} = require('follow-redirects'); 2 | 3 | try_get(); 4 | 5 | function try_get() { 6 | let url = 'http://nodejs.org/dist/index.json'; 7 | 8 | http.get(url,(res) => { 9 | let body = ""; 10 | 11 | if (res.statusCode !== 200) { 12 | throw new Error(`Unable to get Node.js versions from ${url}`); 13 | } 14 | 15 | res.on("data", (chunk) => { 16 | body += chunk; 17 | }); 18 | 19 | res.on("end", () => { 20 | try { 21 | let json = JSON.parse(body); 22 | 23 | for (const el of json.sort()) { 24 | let version = el.version.substring(1, el.version.length) ; 25 | if(version.startsWith(process.argv[2])){ 26 | console.log(version) 27 | return version; 28 | } 29 | } 30 | } catch (error) { 31 | throw error; 32 | }; 33 | }); 34 | 35 | }).on("error", (error) => { 36 | throw new Error(error); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /tools/getVersionAction.js: -------------------------------------------------------------------------------- 1 | const {http} = require('follow-redirects'); 2 | const fs = require("fs"); 3 | 4 | 5 | let url = 'http://nodejs.org/dist/index.json'; 6 | 7 | http.get(url,(res) => { 8 | let body = ""; 9 | 10 | if (res.statusCode !== 200) { 11 | throw new Error(`Unable to get Node.js versions from ${url}`); 12 | } 13 | 14 | res.on("data", (chunk) => { 15 | body += chunk; 16 | }); 17 | 18 | res.on("end", () => { 19 | try { 20 | let json = JSON.parse(body); 21 | let resolved;; 22 | for (const el of json.sort()) { 23 | let version = el.version.substring(1, el.version.length) ; 24 | if(version.startsWith(`${process.argv[2]}.`)){ 25 | fs.writeFileSync('node.txt', version); 26 | console.log(version); 27 | resolved = version; 28 | return; 29 | } 30 | } 31 | if(!resolved ){ 32 | throw `Unable to resolve latest version for Node.js ${process.argv[2]}` 33 | } 34 | } catch (error) { 35 | throw error; 36 | }; 37 | }); 38 | 39 | }).on("error", (error) => { 40 | throw new Error(error); 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /tools/install.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | , path = require('path') 3 | , spawn = require('child_process').spawn 4 | , whereis = require('./whereis'); 5 | 6 | const checkMono = require('./checkMono'); 7 | 8 | if (process.platform === 'win32') { 9 | const libroot = path.resolve(__dirname, '../lib/native/win32') 10 | , lib32bit = path.resolve(libroot, 'ia32') 11 | , lib64bit = path.resolve(libroot, 'x64') 12 | , libarm64 = path.resolve(libroot, 'arm64'); 13 | 14 | function copyFile(filePath, filename) { 15 | return function(copyToDir) { 16 | //console.log( 'copy '+filename+' from '+filePath+' to '+ copyToDir ); 17 | let outFile = path.resolve(copyToDir, filename); 18 | if ( fs.existsSync( outFile ) ) { 19 | // clear readonly: add write permission to ogw (222 octal -> 92 hex -> 146 decimal) 20 | fs.chmodSync( outFile, fs.statSync(outFile).mode | 146 ) 21 | } 22 | fs.writeFileSync(path.resolve(copyToDir, filename), fs.readFileSync(filePath)); 23 | }; 24 | } 25 | 26 | function isDirectory(info) { 27 | return info.isDirectory; 28 | } 29 | 30 | function getInfo(basedir) { 31 | return function(file) { 32 | var filepath = path.resolve(basedir, file); 33 | 34 | return { 35 | path: filepath, 36 | isDirectory: fs.statSync(filepath).isDirectory() 37 | }; 38 | } 39 | } 40 | 41 | function getPath(info) { 42 | return info.path; 43 | } 44 | 45 | function getDestDirs(basedir){ 46 | return fs.readdirSync(basedir) 47 | .map(getInfo(basedir)) 48 | .filter(isDirectory) 49 | .map(getPath); 50 | } 51 | 52 | const redist = [ 53 | 'concrt140.dll', 54 | 'msvcp140.dll', 55 | 'vccorlib140.dll', 56 | 'vcruntime140.dll', 57 | ]; 58 | 59 | const dest32dirs = getDestDirs(lib32bit); 60 | const dest64dirs = getDestDirs(lib64bit); 61 | const destarmdirs = getDestDirs(libarm64); 62 | 63 | function copyRedist(lib, destDirs){ 64 | redist.forEach(function (dllname) { 65 | var dll = path.resolve(lib, dllname); 66 | destDirs.forEach(copyFile(dll, dllname)); 67 | }); 68 | } 69 | 70 | copyRedist(lib32bit, dest32dirs); 71 | copyRedist(lib64bit, dest64dirs); 72 | copyRedist(libarm64, destarmdirs); 73 | 74 | const dotnetPath = whereis('dotnet', 'dotnet.exe'); 75 | 76 | if (dotnetPath) { 77 | spawn(dotnetPath, ['restore'], { stdio: 'inherit', cwd: path.resolve(__dirname, '..', 'lib', 'bootstrap') }) 78 | .on('close', function() { 79 | spawn(dotnetPath, ['build', '--configuration', 'Release'], { stdio: 'inherit', cwd: path.resolve(__dirname, '..', 'lib', 'bootstrap') }) 80 | .on('close', function() { 81 | require('./checkplatform'); 82 | }); 83 | }); 84 | } 85 | 86 | else { 87 | require('./checkplatform'); 88 | } 89 | } 90 | 91 | else { 92 | if(process.platform === 'darwin'){ 93 | 94 | const nodeVersion = process.versions.node.split(".")[0] 95 | const edjeNative = path.resolve(__dirname, '../lib/native/' + process.platform + '/' + process.arch + '/' + nodeVersion + '/' + 'edge_nativeclr.node'); 96 | const edjeNativeClr = path.resolve(__dirname, '../lib/native/' + process.platform + '/' + process.arch + '/' + nodeVersion + '/' + 'edge_coreclr.node'); 97 | 98 | const checkNative = checkMono() ? fs.existsSync(edjeNative) : true; 99 | 100 | if(checkNative && fs.existsSync(edjeNativeClr)){ 101 | 102 | if(fs.existsSync(path.resolve(__dirname, '../build'))){ 103 | fs.rmSync(path.resolve(__dirname, '../build'), { recursive: true, force: true }); 104 | } 105 | 106 | spawn('dotnet', ['build', '--configuration', 'Release'], { stdio: 'inherit', cwd: path.resolve(__dirname, '..', 'lib', 'bootstrap') }) 107 | 108 | } 109 | else{ 110 | spawn('node-gyp', ['configure', 'build'], { stdio: 'inherit' }); 111 | } 112 | } 113 | else{ 114 | spawn('node-gyp', ['configure', 'build'], { stdio: 'inherit' }); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tools/nuget/README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | ### With Edge.js you can script Node.js in a .NET and .NET in Node.js. 4 | 5 | Edge.js allows you to run Node.js and .NET code in one process. You can call Node.js functions from .NET and .NET functions from Node.js. 6 | Edge.js takes care of marshaling data between CLR and V8. Edge.js also reconciles threading models of single-threaded V8 and multi-threaded CLR. Edge.js ensures correct lifetime of objects on V8 and CLR heaps. 7 | 8 | Script CLR from Node.Js on Windows with .NET Framework. 9 | 10 | **NOTE** Scripting Node.Js from CLR is only supported on Windows .NET Framework 4.5 - 4.8 11 | 12 | More documentation is available at [Edge.Js GitHub page](https://github.com/agracio/edge-js). 13 | 14 | #### NuGet package compiled using Node.js v22.12.0. 15 | 16 | ### How to use 17 | 18 | ```cs 19 | using System; 20 | using System.Threading.Tasks; 21 | using EdgeJs; 22 | 23 | class Program 24 | { 25 | public static async Task Start() 26 | { 27 | var func = Edge.Func(@" 28 | return function (data, callback) { 29 | callback(null, 'Node.js welcomes ' + data); 30 | } 31 | "); 32 | 33 | Console.WriteLine(await func(".NET")); 34 | } 35 | 36 | static void Main(string[] args) 37 | { 38 | Start().Wait(); 39 | } 40 | } 41 | 42 | ``` -------------------------------------------------------------------------------- /tools/nuget/build/EdgeJs.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileDirectory)..\content 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | edge\%(RecursiveDir)%(Filename)%(Extension) 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tools/nuget/edge.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EdgeJs 5 | 22.12.0 6 | Tomasz Janczuk 7 | MIT 8 | https://licenses.nuget.org/MIT 9 | https://github.com/agracio/edge-js 10 | 11 | false 12 | Run .NET and Node.js code in one process on Windows, macOS, and Linux 13 | Edge.js allows you to run Node.js and .NET code in one process. You can call Node.js functions from .NET and .NET functions from Node.js. 14 | Copyright 2017 Tomasz Janczuk 15 | node.js .net edge edge.js clr coreclr interop javascript edge-js edgejs 16 | README.md 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tools/nuget/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | function MarkDirectoryAsCopyToOutputRecursive($item) 4 | { 5 | $item.ProjectItems | ForEach-Object { MarkFileASCopyToOutputDirectory($_) } 6 | } 7 | 8 | function MarkFileASCopyToOutputDirectory($item) 9 | { 10 | Try 11 | { 12 | Write-Host Try set $item.Name 13 | $item.Properties.Item("CopyToOutputDirectory").Value = 2 14 | } 15 | Catch 16 | { 17 | Write-Host RecurseOn $item.Name 18 | MarkDirectoryAsCopyToOutputRecursive($item) 19 | } 20 | } 21 | 22 | MarkDirectoryAsCopyToOutputRecursive($project.ProjectItems.Item("edge")) 23 | -------------------------------------------------------------------------------- /tools/whereis.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | module.exports = function() { 5 | var pathSep = process.platform === 'win32' ? ';' : ':'; 6 | 7 | var directories = process.env.PATH.split(pathSep); 8 | 9 | for (var i = 0; i < directories.length; i++) { 10 | for (var j = 0; j < arguments.length; j++) { 11 | var filename = arguments[j]; 12 | var filePath = path.join(directories[i], filename); 13 | 14 | if (fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) { 15 | return filePath; 16 | } 17 | } 18 | } 19 | 20 | return null; 21 | } --------------------------------------------------------------------------------