Deleted ExACTRegressionScripts, starting over
This commit is contained in:
2
ExACTRegressionScripts/.gitignore
vendored
2
ExACTRegressionScripts/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
screenshots
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import express from 'express';
|
|
||||||
|
|
||||||
//import authentication test scripts
|
|
||||||
//import loginTest from './tests/login.js';
|
|
||||||
import ExACT_landingPage from './tests/ExACT_landingPage.js';
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
|
||||||
res.send(`
|
|
||||||
<div style="text-align:center; background:#ccc;" width="100%">
|
|
||||||
|
|
||||||
<h1 style="text-align:center; color:#055a8c; padding-top: 40px;">ExACT</h1>
|
|
||||||
|
|
||||||
<h1 style="text-align:center; color:#001; padding-top: 10px;">Click the corresponding link to exeucate the desired automated test case script:</h1>
|
|
||||||
|
|
||||||
<br><div style="padding:3px;"><strong><a href='/ExACT_landingPage' target='_blank'>Landing Page</a></strong></div>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
})
|
|
||||||
|
|
||||||
//Authentication Test Automations Routes
|
|
||||||
//app.get('/login', loginTest);
|
|
||||||
app.get('/ExACT_landingPage', ExACT_landingPage);
|
|
||||||
|
|
||||||
app.listen(8000, () => {
|
|
||||||
console.log('Server is running on port 8000');
|
|
||||||
});
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/chromedriver
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/chromedriver
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../chromedriver/bin/chromedriver" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../chromedriver/bin/chromedriver" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/chromedriver.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/chromedriver.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\chromedriver\bin\chromedriver" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/chromedriver.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/chromedriver.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../chromedriver/bin/chromedriver" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../chromedriver/bin/chromedriver" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../chromedriver/bin/chromedriver" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../chromedriver/bin/chromedriver" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/crc32
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/crc32
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../crc-32/bin/crc32.njs" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../crc-32/bin/crc32.njs" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/crc32.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/crc32.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\crc-32\bin\crc32.njs" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/crc32.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/crc32.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/escodegen
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/escodegen
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../escodegen/bin/escodegen.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../escodegen/bin/escodegen.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/escodegen.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/escodegen.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\escodegen\bin\escodegen.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/escodegen.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/escodegen.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../escodegen/bin/escodegen.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../escodegen/bin/escodegen.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../escodegen/bin/escodegen.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../escodegen/bin/escodegen.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/esgenerate
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/esgenerate
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../escodegen/bin/esgenerate.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../escodegen/bin/esgenerate.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/esgenerate.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/esgenerate.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\escodegen\bin\esgenerate.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/esgenerate.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/esgenerate.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../escodegen/bin/esgenerate.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../escodegen/bin/esgenerate.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../escodegen/bin/esgenerate.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../escodegen/bin/esgenerate.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/esparse
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/esparse
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../esprima/bin/esparse.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../esprima/bin/esparse.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/esparse.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/esparse.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esprima\bin\esparse.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/esparse.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/esparse.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/esvalidate
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/esvalidate
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../esprima/bin/esvalidate.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../esprima/bin/esvalidate.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/esvalidate.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/esvalidate.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esprima\bin\esvalidate.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/esvalidate.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/esvalidate.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/extract-zip
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/extract-zip
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../extract-zip/cli.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../extract-zip/cli.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/extract-zip.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/extract-zip.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\extract-zip\cli.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/extract-zip.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/extract-zip.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../extract-zip/cli.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../extract-zip/cli.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../extract-zip/cli.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../extract-zip/cli.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/geckodriver
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/geckodriver
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../geckodriver/bin/geckodriver.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../geckodriver/bin/geckodriver.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/geckodriver.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/geckodriver.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\geckodriver\bin\geckodriver.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/geckodriver.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/geckodriver.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../geckodriver/bin/geckodriver.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../geckodriver/bin/geckodriver.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../geckodriver/bin/geckodriver.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../geckodriver/bin/geckodriver.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/mime
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/mime
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../mime/cli.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../mime/cli.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/mime.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/mime.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\mime\cli.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/mime.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/mime.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../mime/cli.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../mime/cli.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../mime/cli.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../mime/cli.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/node-which
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/node-which
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../which/bin/which.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../which/bin/which.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/node-which.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/node-which.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\which.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/node-which.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/node-which.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../which/bin/which.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../which/bin/which.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../which/bin/which.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../which/bin/which.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/nodemon
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/nodemon
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../nodemon/bin/nodemon.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../nodemon/bin/nodemon.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/nodemon.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/nodemon.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nodemon\bin\nodemon.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/nodemon.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/nodemon.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/nodetouch
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/nodetouch
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../touch/bin/nodetouch.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../touch/bin/nodetouch.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/nodetouch.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/nodetouch.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\touch\bin\nodetouch.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/nodetouch.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/nodetouch.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../touch/bin/nodetouch.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../touch/bin/nodetouch.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/semver
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/semver
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../semver/bin/semver.js" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/semver.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/semver.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/semver.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/semver.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../semver/bin/semver.js" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
16
ExACTRegressionScripts/node_modules/.bin/xlsx
generated
vendored
16
ExACTRegressionScripts/node_modules/.bin/xlsx
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
||||||
|
|
||||||
case `uname` in
|
|
||||||
*CYGWIN*|*MINGW*|*MSYS*)
|
|
||||||
if command -v cygpath > /dev/null 2>&1; then
|
|
||||||
basedir=`cygpath -w "$basedir"`
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -x "$basedir/node" ]; then
|
|
||||||
exec "$basedir/node" "$basedir/../xlsx/bin/xlsx.njs" "$@"
|
|
||||||
else
|
|
||||||
exec node "$basedir/../xlsx/bin/xlsx.njs" "$@"
|
|
||||||
fi
|
|
||||||
17
ExACTRegressionScripts/node_modules/.bin/xlsx.cmd
generated
vendored
17
ExACTRegressionScripts/node_modules/.bin/xlsx.cmd
generated
vendored
@@ -1,17 +0,0 @@
|
|||||||
@ECHO off
|
|
||||||
GOTO start
|
|
||||||
:find_dp0
|
|
||||||
SET dp0=%~dp0
|
|
||||||
EXIT /b
|
|
||||||
:start
|
|
||||||
SETLOCAL
|
|
||||||
CALL :find_dp0
|
|
||||||
|
|
||||||
IF EXIST "%dp0%\node.exe" (
|
|
||||||
SET "_prog=%dp0%\node.exe"
|
|
||||||
) ELSE (
|
|
||||||
SET "_prog=node"
|
|
||||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
|
||||||
)
|
|
||||||
|
|
||||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\xlsx\bin\xlsx.njs" %*
|
|
||||||
28
ExACTRegressionScripts/node_modules/.bin/xlsx.ps1
generated
vendored
28
ExACTRegressionScripts/node_modules/.bin/xlsx.ps1
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
|
||||||
|
|
||||||
$exe=""
|
|
||||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
|
||||||
# Fix case when both the Windows and Linux builds of Node
|
|
||||||
# are installed in the same directory
|
|
||||||
$exe=".exe"
|
|
||||||
}
|
|
||||||
$ret=0
|
|
||||||
if (Test-Path "$basedir/node$exe") {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "$basedir/node$exe" "$basedir/../xlsx/bin/xlsx.njs" $args
|
|
||||||
} else {
|
|
||||||
& "$basedir/node$exe" "$basedir/../xlsx/bin/xlsx.njs" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
} else {
|
|
||||||
# Support pipeline input
|
|
||||||
if ($MyInvocation.ExpectingInput) {
|
|
||||||
$input | & "node$exe" "$basedir/../xlsx/bin/xlsx.njs" $args
|
|
||||||
} else {
|
|
||||||
& "node$exe" "$basedir/../xlsx/bin/xlsx.njs" $args
|
|
||||||
}
|
|
||||||
$ret=$LASTEXITCODE
|
|
||||||
}
|
|
||||||
exit $ret
|
|
||||||
2288
ExACTRegressionScripts/node_modules/.package-lock.json
generated
vendored
2288
ExACTRegressionScripts/node_modules/.package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
33
ExACTRegressionScripts/node_modules/@testim/chrome-version/.eslintrc.json
generated
vendored
33
ExACTRegressionScripts/node_modules/@testim/chrome-version/.eslintrc.json
generated
vendored
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"commonjs": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"globals": {
|
|
||||||
"Atomics": "readonly",
|
|
||||||
"SharedArrayBuffer": "readonly"
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"indent": [
|
|
||||||
"error",
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"linebreak-style": [
|
|
||||||
"error",
|
|
||||||
"unix"
|
|
||||||
],
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"single"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
19
ExACTRegressionScripts/node_modules/@testim/chrome-version/.github/workflows/ci.yml
generated
vendored
19
ExACTRegressionScripts/node_modules/@testim/chrome-version/.github/workflows/ci.yml
generated
vendored
@@ -1,19 +0,0 @@
|
|||||||
name: Tests
|
|
||||||
on: [push, pull_request]
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: 'Test on Node.js v${{ matrix.node }} / ${{ matrix.os }}'
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
|
||||||
node: [10, 12, 14, 16]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node }}
|
|
||||||
- run: npm install
|
|
||||||
- run: npm test
|
|
||||||
76
ExACTRegressionScripts/node_modules/@testim/chrome-version/CODE_OF_CONDUCT.md
generated
vendored
76
ExACTRegressionScripts/node_modules/@testim/chrome-version/CODE_OF_CONDUCT.md
generated
vendored
@@ -1,76 +0,0 @@
|
|||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
In the interest of fostering an open and welcoming environment, we as
|
|
||||||
contributors and maintainers pledge to making participation in our project and
|
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
|
||||||
level of experience, education, socio-economic status, nationality, personal
|
|
||||||
appearance, race, religion, or sexual identity and orientation.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment
|
|
||||||
include:
|
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
|
||||||
* Being respectful of differing viewpoints and experiences
|
|
||||||
* Gracefully accepting constructive criticism
|
|
||||||
* Focusing on what is best for the community
|
|
||||||
* Showing empathy towards other community members
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
||||||
advances
|
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or electronic
|
|
||||||
address, without explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Our Responsibilities
|
|
||||||
|
|
||||||
Project maintainers are responsible for clarifying the standards of acceptable
|
|
||||||
behavior and are expected to take appropriate and fair corrective action in
|
|
||||||
response to any instances of unacceptable behavior.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or
|
|
||||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
||||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
||||||
permanently any contributor for other behaviors that they deem inappropriate,
|
|
||||||
threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community. Examples of
|
|
||||||
representing a project or community include using an official project e-mail
|
|
||||||
address, posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event. Representation of a project may be
|
|
||||||
further defined and clarified by project maintainers.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported by contacting the project team at benji@testim.io. All
|
|
||||||
complaints will be reviewed and investigated and will result in a response that
|
|
||||||
is deemed necessary and appropriate to the circumstances. The project team is
|
|
||||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
||||||
Further details of specific enforcement policies may be posted separately.
|
|
||||||
|
|
||||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
||||||
faith may face temporary or permanent repercussions as determined by other
|
|
||||||
members of the project's leadership.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
||||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see
|
|
||||||
https://www.contributor-covenant.org/faq
|
|
||||||
21
ExACTRegressionScripts/node_modules/@testim/chrome-version/LICENSE
generated
vendored
21
ExACTRegressionScripts/node_modules/@testim/chrome-version/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2018-2019 Testim.io
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
51
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/darwin.js
generated
vendored
51
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/darwin.js
generated
vendored
@@ -1,51 +0,0 @@
|
|||||||
const { execSync } = require('child_process');
|
|
||||||
const path = require('path').posix;
|
|
||||||
const { canAccess, newLineRegex, sort } = require('./util');
|
|
||||||
|
|
||||||
function darwin(includeChromium = false) {
|
|
||||||
const suffixes = [
|
|
||||||
// '/Contents/MacOS/Google Chrome Canary',
|
|
||||||
'/Contents/MacOS/Google Chrome',
|
|
||||||
... includeChromium ? ['/Contents/MacOS/Chromium'] : []
|
|
||||||
];
|
|
||||||
|
|
||||||
const LSREGISTER = '/System/Library/Frameworks/CoreServices.framework' +
|
|
||||||
'/Versions/A/Frameworks/LaunchServices.framework' +
|
|
||||||
'/Versions/A/Support/lsregister';
|
|
||||||
|
|
||||||
const installations = [];
|
|
||||||
|
|
||||||
execSync(
|
|
||||||
`${LSREGISTER} -dump` +
|
|
||||||
' | grep -E -i \'(google chrome( canary)?' + (includeChromium ? '|chromium' : '') + ').app(\\s\\(0x[0-9a-f]+\\))?$\'' +
|
|
||||||
' | awk \'sub(/\\(0x[0-9a-f]+\\)/, "")\'' +
|
|
||||||
' | awk \'{$1=""; print $0}\'' +
|
|
||||||
' | awk \'{ gsub(/^[ \\t]+|[ \\t]+$/, ""); print }\'')
|
|
||||||
.toString()
|
|
||||||
.split(newLineRegex)
|
|
||||||
.forEach((inst) => {
|
|
||||||
suffixes.forEach(suffix => {
|
|
||||||
const execPath = path.join(inst.trim(), suffix);
|
|
||||||
if (canAccess(execPath)) {
|
|
||||||
installations.push(execPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Retains one per line to maintain readability.
|
|
||||||
const priorities = [
|
|
||||||
{ regex: new RegExp(`^${process.env.HOME}/Applications/.*Chromium.app`), weight: 49 },
|
|
||||||
{ regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome.app`), weight: 50 },
|
|
||||||
// { regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome Canary.app`), weight: 51 },
|
|
||||||
{ regex: /^\/Applications\/.*Chromium.app/, weight: 99 },
|
|
||||||
{ regex: /^\/Applications\/.*Chrome.app/, weight: 100 },
|
|
||||||
// { regex: /^\/Applications\/.*Chrome Canary.app/, weight: 101 },
|
|
||||||
{ regex: /^\/Volumes\/.*Chromium.app/, weight: -3 },
|
|
||||||
{ regex: /^\/Volumes\/.*Chrome.app/, weight: -2 },
|
|
||||||
// { regex: /^\/Volumes\/.*Chrome Canary.app/, weight: -1 }
|
|
||||||
];
|
|
||||||
|
|
||||||
return sort(installations, priorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = darwin;
|
|
||||||
9
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/index.d.ts
generated
vendored
9
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/index.d.ts
generated
vendored
@@ -1,9 +0,0 @@
|
|||||||
/**
|
|
||||||
* find a executable chrome for all support system
|
|
||||||
* @returns {string} executable chrome full path
|
|
||||||
* @throws
|
|
||||||
* if no executable chrome find, ERROR_NO_INSTALLATIONS_FOUND will be throw
|
|
||||||
* if platform is not one if ['win32','darwin','linux'], ERROR_PLATFORM_NOT_SUPPORT will be throw
|
|
||||||
*/
|
|
||||||
declare function findChrome(): string;
|
|
||||||
export = findChrome;
|
|
||||||
39
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/index.js
generated
vendored
39
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/index.js
generated
vendored
@@ -1,39 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const ERROR_PLATFORM_NOT_SUPPORT = new Error('platform not support');
|
|
||||||
const ERROR_NO_INSTALLATIONS_FOUND = new Error('no chrome installations found');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a executable Chrome (or Chromium) for all supported systems.
|
|
||||||
*
|
|
||||||
* Supports macOS, Linux, and Windows.
|
|
||||||
*
|
|
||||||
* @param {boolean} includeChromium true if we should consider Chromium in our search, false otherwise.
|
|
||||||
* @returns {string} the first full path to an executable Chrome (or Chromium)
|
|
||||||
* @throws
|
|
||||||
* if no executable Chrome (or Chromium) find, ERROR_NO_INSTALLATIONS_FOUND will be throw
|
|
||||||
* if platform is not one if ['win32','darwin','linux'], ERROR_PLATFORM_NOT_SUPPORT will be throw
|
|
||||||
*/
|
|
||||||
function findChrome(includeChromium = false) {
|
|
||||||
const { platform } = process;
|
|
||||||
let installations = [];
|
|
||||||
switch (platform) {
|
|
||||||
case 'win32':
|
|
||||||
installations = require('./win32')(includeChromium);
|
|
||||||
break;
|
|
||||||
case 'darwin':
|
|
||||||
installations = require('./darwin')(includeChromium);
|
|
||||||
break;
|
|
||||||
case 'linux':
|
|
||||||
installations = require('./linux')(includeChromium);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw ERROR_PLATFORM_NOT_SUPPORT;
|
|
||||||
}
|
|
||||||
if (installations.length) {
|
|
||||||
return installations[0];
|
|
||||||
} else {
|
|
||||||
throw ERROR_NO_INSTALLATIONS_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = findChrome;
|
|
||||||
112
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/linux.js
generated
vendored
112
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/linux.js
generated
vendored
@@ -1,112 +0,0 @@
|
|||||||
const { execSync, execFileSync } = require('child_process');
|
|
||||||
const path = require('path').posix;
|
|
||||||
const fs = require('fs');
|
|
||||||
const { canAccess, sort, isExecutable, newLineRegex } = require('./util');
|
|
||||||
|
|
||||||
|
|
||||||
function findChromeExecutablesForLinuxDesktop(folder, includeChromium = false) {
|
|
||||||
const argumentsRegex = /(^[^ ]+).*/; // Take everything up to the first space
|
|
||||||
const chromeExecRegex = '^Exec=\/.*\/(google|chrome' + (includeChromium ? '|chromium' : '') + ')-.*';
|
|
||||||
|
|
||||||
let installations = [];
|
|
||||||
if (canAccess(folder)) {
|
|
||||||
// Output of the grep & print looks like:
|
|
||||||
// /opt/google/chrome/google-chrome --profile-directory
|
|
||||||
// /home/user/Downloads/chrome-linux/chrome-wrapper %U
|
|
||||||
let execPaths;
|
|
||||||
execPaths = execSync(`find "${folder}" -type f -exec grep -E "${chromeExecRegex}" "{}" \\; | awk -F '=' '{print $2}'`);
|
|
||||||
|
|
||||||
execPaths = execPaths
|
|
||||||
.toString()
|
|
||||||
.split(newLineRegex)
|
|
||||||
.map((execPath) => execPath.replace(argumentsRegex, '$1'));
|
|
||||||
|
|
||||||
execPaths.forEach((execPath) => canAccess(execPath) && installations.push(execPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
return installations;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findChromeExecutablesForLinux(validChromePaths, includeChromium = false) {
|
|
||||||
const executables = [
|
|
||||||
'google-chrome-stable',
|
|
||||||
'google-chrome',
|
|
||||||
... includeChromium ? ['chromium', 'chromium-browser', 'chromium/chrome'] : [] // chromium/chrome is for toradex machines where "chromium" is a directory. seen on Angstrom v2016.12
|
|
||||||
];
|
|
||||||
|
|
||||||
return executables.map(executable => {
|
|
||||||
const existingPaths = validChromePaths.map(possiblePath => {
|
|
||||||
try {
|
|
||||||
const chromePathToTest = possiblePath + '/' + executable;
|
|
||||||
if (fs.existsSync(chromePathToTest) && canAccess(chromePathToTest) && isExecutable(chromePathToTest)) {
|
|
||||||
return [ chromePathToTest ];
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// not installed on this path or inaccessible
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}).reduce((acc, val) => acc.concat(val), []); //.filter((foundChromePath) => foundChromePath);
|
|
||||||
|
|
||||||
// skip asking "which" command if the binary was found by searching the known paths.
|
|
||||||
if (existingPaths && existingPaths.length > 0) {
|
|
||||||
return existingPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const chromePath = execFileSync('which', [executable]).toString().split(newLineRegex)[0];
|
|
||||||
if (canAccess(chromePath)) {
|
|
||||||
return [ chromePath ];
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// cmd which not installed.
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
|
|
||||||
}).reduce((acc, val) => acc.concat(val), []);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look for linux executables in 2 ways
|
|
||||||
* 1. Look into the directories where .desktop are saved on gnome based distro's
|
|
||||||
* 2. Look for google-chrome-stable and google-chrome executables by using the which command
|
|
||||||
* If includeChromium is set, also look for chromium, chromium-browser, and chromium/chrome executables by using the which command
|
|
||||||
*/
|
|
||||||
function linux(includeChromium = false) {
|
|
||||||
let installations = [];
|
|
||||||
|
|
||||||
// 1. Look into the directories where .desktop are saved on gnome based distro's
|
|
||||||
const desktopInstallationFolders = [
|
|
||||||
path.join(require('os').homedir(), '.local/share/applications/'),
|
|
||||||
'/usr/share/applications/',
|
|
||||||
];
|
|
||||||
desktopInstallationFolders.forEach(folder => {
|
|
||||||
installations = installations.concat(findChromeExecutablesForLinuxDesktop(folder, includeChromium));
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Look for google-chrome-stable and google-chrome (and optionally chromium, chromium-browser, and chromium-chrome) executables by using the which command
|
|
||||||
// see http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/
|
|
||||||
const validChromePaths = [
|
|
||||||
'/usr/bin',
|
|
||||||
'/usr/local/bin',
|
|
||||||
'/usr/sbin',
|
|
||||||
'/usr/local/sbin',
|
|
||||||
'/opt/bin',
|
|
||||||
'/usr/bin/X11',
|
|
||||||
'/usr/X11R6/bin'
|
|
||||||
];
|
|
||||||
installations = installations.concat(findChromeExecutablesForLinux(validChromePaths, includeChromium));
|
|
||||||
|
|
||||||
const priorities = [
|
|
||||||
{ regex: /chromium$/, weight: 52 },
|
|
||||||
{ regex: /chrome-wrapper$/, weight: 51 },
|
|
||||||
{ regex: /google-chrome-stable$/, weight: 50 },
|
|
||||||
{ regex: /google-chrome$/, weight: 49 },
|
|
||||||
{ regex: /chromium-browser$/, weight: 48 },
|
|
||||||
{ regex: /chrome$/, weight: 47 },
|
|
||||||
];
|
|
||||||
|
|
||||||
return sort(Array.from(new Set(installations.filter(Boolean))), priorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = linux;
|
|
||||||
56
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/util.js
generated
vendored
56
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/util.js
generated
vendored
@@ -1,56 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const newLineRegex = /\r?\n/;
|
|
||||||
|
|
||||||
function sort(installations, priorities) {
|
|
||||||
const defaultPriority = 10;
|
|
||||||
// assign priorities
|
|
||||||
return installations
|
|
||||||
.map((inst) => {
|
|
||||||
for (const pair of priorities) {
|
|
||||||
if (pair.regex.test(inst)) {
|
|
||||||
return { path: inst, weight: pair.weight };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { path: inst, weight: defaultPriority };
|
|
||||||
})
|
|
||||||
// sort based on priorities
|
|
||||||
.sort((a, b) => (b.weight - a.weight))
|
|
||||||
// remove priority flag
|
|
||||||
.map(pair => pair.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
function canAccess(file) {
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.accessSync(file);
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isExecutable(file) {
|
|
||||||
if (!file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var stat = fs.statSync(file);
|
|
||||||
return stat && typeof stat.isFile === "function" && stat.isFile();
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
sort,
|
|
||||||
canAccess,
|
|
||||||
isExecutable,
|
|
||||||
newLineRegex,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
30
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/win32.js
generated
vendored
30
ExACTRegressionScripts/node_modules/@testim/chrome-version/chrome-finder/win32.js
generated
vendored
@@ -1,30 +0,0 @@
|
|||||||
const path = require('path').win32;
|
|
||||||
const { canAccess } = require('./util');
|
|
||||||
const procesEnv = process.env;
|
|
||||||
|
|
||||||
|
|
||||||
function win32(includeChromium = false) {
|
|
||||||
const installations = [];
|
|
||||||
const suffixes = [
|
|
||||||
'\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'\\chrome-win32\\chrome.exe',
|
|
||||||
... includeChromium ? ['\\Chromium\\Application\\chrome.exe'] : [],
|
|
||||||
// '\\Google\\Chrome Beta\\Application\\chrome.exe',
|
|
||||||
];
|
|
||||||
const prefixes = [
|
|
||||||
procesEnv.LOCALAPPDATA,
|
|
||||||
procesEnv.PROGRAMFILES,
|
|
||||||
procesEnv['PROGRAMFILES(X86)']
|
|
||||||
].filter(prefix => prefix); // filter out undefined
|
|
||||||
|
|
||||||
prefixes.forEach(prefix => suffixes.forEach(suffix => {
|
|
||||||
const chromePath = path.join(prefix, suffix);
|
|
||||||
if (canAccess(chromePath)) {
|
|
||||||
installations.push(chromePath);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return installations;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = win32;
|
|
||||||
6
ExACTRegressionScripts/node_modules/@testim/chrome-version/example.js
generated
vendored
6
ExACTRegressionScripts/node_modules/@testim/chrome-version/example.js
generated
vendored
@@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
(async () => {
|
|
||||||
const { getChromeVersion } = require('./index');
|
|
||||||
const version = await getChromeVersion();
|
|
||||||
console.log(version);
|
|
||||||
})();
|
|
||||||
130
ExACTRegressionScripts/node_modules/@testim/chrome-version/index.js
generated
vendored
130
ExACTRegressionScripts/node_modules/@testim/chrome-version/index.js
generated
vendored
@@ -1,130 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const findChrome = require('./chrome-finder');
|
|
||||||
const util = require('util');
|
|
||||||
const exec = util.promisify(require('child_process').exec);
|
|
||||||
const path = require('path');
|
|
||||||
const readdir = util.promisify(require('fs').readdir);
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
|
|
||||||
async function getChromeVersionFromCli(includeChromium) {
|
|
||||||
|
|
||||||
let chromePath;
|
|
||||||
try {
|
|
||||||
chromePath = findChrome(includeChromium);
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await exec(chromePath.replace(/ /g, '\\ ') + ' --version');
|
|
||||||
|
|
||||||
const version = extractChromeVersionNumer(res.stdout);
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractChromeVersionNumer(chromeVersionString) {
|
|
||||||
return chromeVersionString.replace(/\D*(([0-9]+\.?)+)\s?.*/, '$1');
|
|
||||||
}
|
|
||||||
|
|
||||||
const chromeVersionRegex = /^(\d+\.){3}\d+$/g;
|
|
||||||
|
|
||||||
async function getChromeVersionWin(includeChromium) {
|
|
||||||
|
|
||||||
let chromePath;
|
|
||||||
try {
|
|
||||||
chromePath = findChrome(includeChromium);
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const powershell = await execAndAttemptExtractingChromeVersion(`powershell -command "&{(Get-Item '${chromePath}').VersionInfo.ProductVersion}"`);
|
|
||||||
if (powershell !== null) {
|
|
||||||
return powershell;
|
|
||||||
}
|
|
||||||
|
|
||||||
const registry = await execAndAttemptExtractingChromeVersion('reg query "HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon" /v version');
|
|
||||||
if (registry !== null) {
|
|
||||||
return registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionPath = path.dirname(chromePath);
|
|
||||||
|
|
||||||
const contents = await readdir(versionPath);
|
|
||||||
|
|
||||||
const versions = contents.filter(a => chromeVersionRegex.test(a));
|
|
||||||
|
|
||||||
// returning oldest in case there is an updated version and chrome still hasn't relaunched
|
|
||||||
const oldest = versions.sort((a, b) => a > b)[0];
|
|
||||||
|
|
||||||
return oldest;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function execAndAttemptExtractingChromeVersion(command) {
|
|
||||||
try {
|
|
||||||
const { stdout } = await exec(command);
|
|
||||||
const version = extractChromeVersionNumer(stdout).trim();
|
|
||||||
if (chromeVersionRegex.test(version)) {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
} catch (err) { ''; }
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChromeVersionFromOsa(includeChromium) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
const version = execSync('osascript -e \'tell application "Google Chrome" to get version\'').toString().trim();
|
|
||||||
return version;
|
|
||||||
} catch (err) {
|
|
||||||
if (!includeChromium) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// else fall-through to check for Chromium below
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const version = execSync('osascript -e \'tell application "Chromium" to get version\'').toString().trim();
|
|
||||||
return version;
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function innerGetChromeVersion(includeChromium = false) {
|
|
||||||
|
|
||||||
const os = process.platform;
|
|
||||||
|
|
||||||
if (os === 'darwin') return getChromeVersionFromOsa(includeChromium);
|
|
||||||
if (os === 'linux') return getChromeVersionFromCli(includeChromium);
|
|
||||||
if (os.includes('win')) return getChromeVersionWin(includeChromium);
|
|
||||||
|
|
||||||
console.log(`${os} is not supported`);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the version of Chrome (or Chromium) that is installed.
|
|
||||||
*
|
|
||||||
* Supports macOS, Linux, and Windows.
|
|
||||||
*
|
|
||||||
* @param {boolean} includeChromium true if we should consider Chromium in our search, false otherwise.
|
|
||||||
* @returns {string} the version number of Chrome (or Chromium), or null if the OS is not supported.
|
|
||||||
*/
|
|
||||||
async function getChromeVersion(includeChromium = false) {
|
|
||||||
const res = await innerGetChromeVersion(includeChromium);
|
|
||||||
if (typeof res === 'string') {
|
|
||||||
return res.trim();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main == module) {
|
|
||||||
getChromeVersion().then(v => console.log(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getChromeVersion
|
|
||||||
};
|
|
||||||
27
ExACTRegressionScripts/node_modules/@testim/chrome-version/package.json
generated
vendored
27
ExACTRegressionScripts/node_modules/@testim/chrome-version/package.json
generated
vendored
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@testim/chrome-version",
|
|
||||||
"version": "1.1.4",
|
|
||||||
"description": "Finds the version of Chrome that is installed on your machine",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"lint": "eslint *.js --fix",
|
|
||||||
"test": "mocha"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/testimio/chrome-version.git"
|
|
||||||
},
|
|
||||||
"author": "Testim",
|
|
||||||
"license": "MIT",
|
|
||||||
"homepage": "https://github.com/testimio/chrome-version",
|
|
||||||
"keywords": [
|
|
||||||
"chrome",
|
|
||||||
"version"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"chai": "4.3.4",
|
|
||||||
"eslint": "8.7.0",
|
|
||||||
"mocha": "9.1.4",
|
|
||||||
"rewire": "6.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27
ExACTRegressionScripts/node_modules/@testim/chrome-version/readme.MD
generated
vendored
27
ExACTRegressionScripts/node_modules/@testim/chrome-version/readme.MD
generated
vendored
@@ -1,27 +0,0 @@
|
|||||||
# chrome-version
|
|
||||||
|
|
||||||
[](https://github.com/testimio/chrome-version/actions/workflows/ci.yml)
|
|
||||||
|
|
||||||
Finds the version of Chrome (or Chromium) that is installed on your machine.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
```sh
|
|
||||||
npm install @testim/chrome-version
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use
|
|
||||||
```js
|
|
||||||
(async () => {
|
|
||||||
const { getChromeVersion } = require('@testim/chrome-version');
|
|
||||||
const includeChromium = false; // NOTE: set to true to also search for Chromium
|
|
||||||
const version = await getChromeVersion(includeChromium);
|
|
||||||
console.log(version);
|
|
||||||
})();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
```sh
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
* If no version of chrome is installed on your machine `getChromeVersion` will return null.
|
|
||||||
370
ExACTRegressionScripts/node_modules/@testim/chrome-version/test/test.js
generated
vendored
370
ExACTRegressionScripts/node_modules/@testim/chrome-version/test/test.js
generated
vendored
@@ -1,370 +0,0 @@
|
|||||||
const chai = require('chai');
|
|
||||||
const expect = chai.expect;
|
|
||||||
const Buffer = require('buffer').Buffer;
|
|
||||||
|
|
||||||
// rewrite to get access for testing
|
|
||||||
const rewire = require("rewire");
|
|
||||||
const chromeVersionModule = rewire("../index.js");
|
|
||||||
const extractChromeVersionNumer = chromeVersionModule.__get__('extractChromeVersionNumer');
|
|
||||||
const getChromeVersionFromOsa = chromeVersionModule.__get__('getChromeVersionFromOsa');
|
|
||||||
const chromeFinderLinuxModule = rewire("../chrome-finder/linux.js");
|
|
||||||
const findChromeExecutablesForLinuxDesktop = chromeFinderLinuxModule.__get__('findChromeExecutablesForLinuxDesktop');
|
|
||||||
const findChromeExecutablesForLinux = chromeFinderLinuxModule.__get__('findChromeExecutablesForLinux');
|
|
||||||
const chromeFinderDarwinModule = rewire("../chrome-finder/darwin.js");
|
|
||||||
const findChromeForDarwin = chromeFinderDarwinModule.__get__('darwin');
|
|
||||||
const chromeFinderWin32Module = rewire("../chrome-finder/win32.js");
|
|
||||||
const findChromeForWin32 = chromeFinderWin32Module.__get__('win32');
|
|
||||||
|
|
||||||
describe('Chrome Finder', function() {
|
|
||||||
|
|
||||||
describe('extractChromeVersionNumer from Google Chrome 95.0.4638', function() {
|
|
||||||
it('should return "95.0.4638"', function() {
|
|
||||||
const versionString = 'Google Chrome 95.0.4638';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('95.0.4638');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('extractChromeVersionNumer from Google Chrome 96.0.4664.110', function() {
|
|
||||||
it('should return "96.0.4664.110"', function() {
|
|
||||||
const versionString = 'Google Chrome 96.0.4664.110';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('96.0.4664.110');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('extractChromeVersionNumer from Google Chrome 97.0.4692.71', function() {
|
|
||||||
it('should return "97.0.4692.71"', function() {
|
|
||||||
const versionString = 'Google Chrome 97.0.4692.71';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('97.0.4692.71');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('extractChromiumVersionNumer from Chromium 105.0.5195.102 built on Debian 11.4, running on Debian 11.5', function() {
|
|
||||||
it('should return "105.0.5195.102"', function() {
|
|
||||||
const versionString = 'Chromium 105.0.5195.102 built on Debian 11.4, running on Debian 11.5';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('105.0.5195.102');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('extractChromiumVersionNumer from Chromium 90.0.4430.212 Fedora Project', function() {
|
|
||||||
it('should return "90.0.4430.212"', function() {
|
|
||||||
const versionString = 'Chromium 90.0.4430.212 Fedora Project';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('90.0.4430.212');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('extractChromiumVersionNumer from Chromium 98.0.4753.0', function() {
|
|
||||||
it('should return "98.0.4753.0"', function() {
|
|
||||||
const versionString = 'Chromium 98.0.4753.0';
|
|
||||||
const versionNumber = extractChromeVersionNumer(versionString);
|
|
||||||
expect(versionNumber).to.equal('98.0.4753.0');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getChromeVersionFromOsa when includeChromium=false', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
const includeChromium = false;
|
|
||||||
|
|
||||||
const mockVersion = '97.0.4692.71';
|
|
||||||
|
|
||||||
var execSyncCommand;
|
|
||||||
chromeVersionModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommand = command;
|
|
||||||
return Buffer.from(mockVersion);
|
|
||||||
});
|
|
||||||
|
|
||||||
const version = getChromeVersionFromOsa(includeChromium);
|
|
||||||
|
|
||||||
expect(execSyncCommand).to.include('Google Chrome');
|
|
||||||
expect(execSyncCommand).to.not.include('Chromium');
|
|
||||||
|
|
||||||
expect(version).to.equal(mockVersion);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getChromeVersionFromOsa when includeChromium=true', function() {
|
|
||||||
it('should only find Chromium', function() {
|
|
||||||
const includeChromium = true;
|
|
||||||
|
|
||||||
const mockVersion = '98.0.4753.0';
|
|
||||||
|
|
||||||
var execSyncCommands = [];
|
|
||||||
chromeVersionModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommands.push(command);
|
|
||||||
if (execSyncCommands.length == 1) {
|
|
||||||
throw "not found"
|
|
||||||
}
|
|
||||||
return Buffer.from(mockVersion);
|
|
||||||
});
|
|
||||||
|
|
||||||
const version = getChromeVersionFromOsa(includeChromium);
|
|
||||||
|
|
||||||
expect(execSyncCommands.length).equal(2);
|
|
||||||
expect(execSyncCommands[0]).to.include('Google Chrome');
|
|
||||||
expect(execSyncCommands[1]).to.include('Chromium');
|
|
||||||
|
|
||||||
expect(version).to.equal(mockVersion);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Chrome Finder Linux Module', function() {
|
|
||||||
|
|
||||||
describe('Linux Desktop when includeChromium=false', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = false;
|
|
||||||
|
|
||||||
const mockChromePaths = [
|
|
||||||
'/opt/google/chrome/google-chrome',
|
|
||||||
'/home/user/Downloads/chrome-linux/chrome-wrapper'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderLinuxModule.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var execSyncCommand;
|
|
||||||
chromeFinderLinuxModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommand = command;
|
|
||||||
return Buffer.from(mockChromePaths.join('\n'));
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockDesktopFolder = "mock-desktop-folder";
|
|
||||||
const executables = findChromeExecutablesForLinuxDesktop(mockDesktopFolder, includeChromium);
|
|
||||||
|
|
||||||
expect(execSyncCommand).to.include(mockDesktopFolder);
|
|
||||||
expect(execSyncCommand).to.not.include('|chromium');
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(2);
|
|
||||||
expect(executables).to.deep.equal(mockChromePaths);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Linux Desktop when includeChromium=true', function() {
|
|
||||||
it('should find Chrome and Chromium', function() {
|
|
||||||
|
|
||||||
const includeChromium = true;
|
|
||||||
|
|
||||||
const mockChromePaths = [
|
|
||||||
'/opt/google/chrome/google-chrome',
|
|
||||||
'/home/user/Downloads/chrome-linux/chrome-wrapper',
|
|
||||||
'/usr/local/bin/chromium-browser'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderLinuxModule.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var execSyncCommand;
|
|
||||||
chromeFinderLinuxModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommand = command;
|
|
||||||
return Buffer.from(mockChromePaths.join('\n'));
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockDesktopFolder = "mock-desktop-folder";
|
|
||||||
const executables = findChromeExecutablesForLinuxDesktop(mockDesktopFolder, includeChromium);
|
|
||||||
|
|
||||||
expect(execSyncCommand).to.include(mockDesktopFolder);
|
|
||||||
expect(execSyncCommand).to.include('|chromium');
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(3);
|
|
||||||
expect(executables).to.deep.equal(mockChromePaths);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Linux when includeChromium=false', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = false;
|
|
||||||
|
|
||||||
const mockPaths = [
|
|
||||||
'/mock-path'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderLinuxModule.__set__('fs', {
|
|
||||||
existsSync: function(file) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
chromeFinderLinuxModule.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
chromeFinderLinuxModule.__set__('isExecutable', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeExecutablesForLinux(mockPaths, includeChromium);
|
|
||||||
expect(executables).to.have.lengthOf(2);
|
|
||||||
|
|
||||||
const expectedExecutables = mockPaths.map(mockPath => ['google-chrome-stable', 'google-chrome'].map(executable => mockPath + '/' + executable)).reduce((acc, val) => acc.concat(val), []);
|
|
||||||
expect(executables).to.deep.equal(expectedExecutables);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Linux when includeChromium=true', function() {
|
|
||||||
it('should find Chrome and Chromium', function() {
|
|
||||||
|
|
||||||
const includeChromium = true;
|
|
||||||
|
|
||||||
const mockPaths = [
|
|
||||||
'/mock-path'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderLinuxModule.__set__('fs', {
|
|
||||||
existsSync: function(file) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
chromeFinderLinuxModule.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
chromeFinderLinuxModule.__set__('isExecutable', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeExecutablesForLinux(mockPaths, includeChromium);
|
|
||||||
expect(executables).to.have.lengthOf(5);
|
|
||||||
|
|
||||||
const expectedExecutables = mockPaths.map(mockPath => ['google-chrome-stable', 'google-chrome', 'chromium', 'chromium-browser', 'chromium/chrome'].map(executable => mockPath + '/' + executable)).reduce((acc, val) => acc.concat(val), []);
|
|
||||||
expect(executables).to.deep.equal(expectedExecutables);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Chrome Finder Darwin Module', function() {
|
|
||||||
|
|
||||||
describe('Darwin when includeChromium=false', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = false;
|
|
||||||
|
|
||||||
const mockChromePaths = [
|
|
||||||
'/Applications/Google Chrome.app'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderDarwinModule.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var execSyncCommand;
|
|
||||||
chromeFinderDarwinModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommand = command;
|
|
||||||
return Buffer.from(mockChromePaths.join('\n'));
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeForDarwin(includeChromium);
|
|
||||||
expect(execSyncCommand).to.not.include('|chromium');
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(1);
|
|
||||||
expect(executables).to.deep.equal(mockChromePaths.map(mockChromePath => mockChromePath + '/Contents/MacOS/Google Chrome'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Darwin when includeChromium=true', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = true;
|
|
||||||
|
|
||||||
const mockChromePaths = [
|
|
||||||
'/Applications/Google Chrome.app',
|
|
||||||
'/Applications/Chromium.app'
|
|
||||||
];
|
|
||||||
|
|
||||||
const expectedExecutables = [
|
|
||||||
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
||||||
'/Applications/Chromium.app/Contents/MacOS/Chromium'
|
|
||||||
];
|
|
||||||
|
|
||||||
chromeFinderDarwinModule.__set__('canAccess', function(file) {
|
|
||||||
return expectedExecutables.includes(file);
|
|
||||||
});
|
|
||||||
|
|
||||||
var execSyncCommand;
|
|
||||||
chromeFinderDarwinModule.__set__('execSync', function(command) {
|
|
||||||
execSyncCommand = command;
|
|
||||||
return Buffer.from(mockChromePaths.join('\n'));
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeForDarwin(includeChromium);
|
|
||||||
expect(execSyncCommand).to.include('|chromium');
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(2);
|
|
||||||
expect(executables).to.deep.equal(expectedExecutables);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Chrome Finder Win32 Module', function() {
|
|
||||||
|
|
||||||
describe('Win32 when includeChromium=false', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = false;
|
|
||||||
|
|
||||||
chromeFinderWin32Module.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
chromeFinderWin32Module.__set__('procesEnv', {
|
|
||||||
LOCALAPPDATA: 'mock-local-app-data',
|
|
||||||
PROGRAMFILES: 'mock-program-files',
|
|
||||||
'PROGRAMFILES(X86)': 'mock-program-files-x86'
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeForWin32(includeChromium);
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(9);
|
|
||||||
expect(executables).to.deep.equal([
|
|
||||||
'mock-local-app-data\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-local-app-data\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-local-app-data\\chrome-win32\\chrome.exe',
|
|
||||||
'mock-program-files\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-program-files\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-program-files\\chrome-win32\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\chrome-win32\\chrome.exe'
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Win32 when includeChromium=true', function() {
|
|
||||||
it('should only find Chrome', function() {
|
|
||||||
|
|
||||||
const includeChromium = true;
|
|
||||||
|
|
||||||
chromeFinderWin32Module.__set__('canAccess', function(file) {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
chromeFinderWin32Module.__set__('procesEnv', {
|
|
||||||
LOCALAPPDATA: 'mock-local-app-data',
|
|
||||||
PROGRAMFILES: 'mock-program-files',
|
|
||||||
'PROGRAMFILES(X86)': 'mock-program-files-x86'
|
|
||||||
});
|
|
||||||
|
|
||||||
const executables = findChromeForWin32(includeChromium);
|
|
||||||
|
|
||||||
expect(executables).to.have.lengthOf(12);
|
|
||||||
expect(executables).to.deep.equal([
|
|
||||||
'mock-local-app-data\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-local-app-data\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-local-app-data\\chrome-win32\\chrome.exe',
|
|
||||||
'mock-local-app-data\\Chromium\\Application\\chrome.exe',
|
|
||||||
'mock-program-files\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-program-files\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-program-files\\chrome-win32\\chrome.exe',
|
|
||||||
'mock-program-files\\Chromium\\Application\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\Google\\Chrome SxS\\Application\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\Google\\Chrome\\Application\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\chrome-win32\\chrome.exe',
|
|
||||||
'mock-program-files-x86\\Chromium\\Application\\chrome.exe'
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
21
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/LICENSE
generated
vendored
21
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
quickjs-emscripten copyright (c) 2019 Jake Teton-Landis
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
597
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/README.md
generated
vendored
597
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/README.md
generated
vendored
@@ -1,597 +0,0 @@
|
|||||||
# quickjs-emscripten
|
|
||||||
|
|
||||||
Javascript/Typescript bindings for QuickJS, a modern Javascript interpreter,
|
|
||||||
compiled to WebAssembly.
|
|
||||||
|
|
||||||
- Safely evaluate untrusted Javascript (up to ES2020).
|
|
||||||
- Create and manipulate values inside the QuickJS runtime ([more][values]).
|
|
||||||
- Expose host functions to the QuickJS runtime ([more][functions]).
|
|
||||||
- Execute synchronous code that uses asynchronous functions, with [asyncify][asyncify].
|
|
||||||
|
|
||||||
[Github] | [NPM] | [API Documentation][api] | [Examples][tests]
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { getQuickJS } from "quickjs-emscripten"
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const QuickJS = await getQuickJS()
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
|
|
||||||
const world = vm.newString("world")
|
|
||||||
vm.setProp(vm.global, "NAME", world)
|
|
||||||
world.dispose()
|
|
||||||
|
|
||||||
const result = vm.evalCode(`"Hello " + NAME + "!"`)
|
|
||||||
if (result.error) {
|
|
||||||
console.log("Execution failed:", vm.dump(result.error))
|
|
||||||
result.error.dispose()
|
|
||||||
} else {
|
|
||||||
console.log("Success:", vm.dump(result.value))
|
|
||||||
result.value.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
[github]: https://github.com/justjake/quickjs-emscripten
|
|
||||||
[npm]: https://www.npmjs.com/package/quickjs-emscripten
|
|
||||||
[api]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/modules.md
|
|
||||||
[tests]: https://github.com/justjake/quickjs-emscripten/blob/main/ts/quickjs.test.ts
|
|
||||||
[values]: #interfacing-with-the-interpreter
|
|
||||||
[asyncify]: #asyncify
|
|
||||||
[functions]: #exposing-apis
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Install from `npm`: `npm install --save quickjs-emscripten` or `yarn add quickjs-emscripten`.
|
|
||||||
|
|
||||||
The root entrypoint of this library is the `getQuickJS` function, which returns
|
|
||||||
a promise that resolves to a [QuickJS singleton](./doc/classes/quickjs.md) when
|
|
||||||
the QuickJS WASM module is ready.
|
|
||||||
|
|
||||||
Once `getQuickJS` has been awaited at least once, you also can use the `getQuickJSSync`
|
|
||||||
function to directly access the singleton engine in your synchronous code.
|
|
||||||
|
|
||||||
### Safely evaluate Javascript code
|
|
||||||
|
|
||||||
See [QuickJS.evalCode](https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/quickjs.md#evalcode)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { getQuickJS, shouldInterruptAfterDeadline } from "quickjs-emscripten"
|
|
||||||
|
|
||||||
getQuickJS().then((QuickJS) => {
|
|
||||||
const result = QuickJS.evalCode("1 + 1", {
|
|
||||||
shouldInterrupt: shouldInterruptAfterDeadline(Date.now() + 1000),
|
|
||||||
memoryLimitBytes: 1024 * 1024,
|
|
||||||
})
|
|
||||||
console.log(result)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Interfacing with the interpreter
|
|
||||||
|
|
||||||
You can use [QuickJSContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/QuickJSContext.md)
|
|
||||||
to build a scripting environment by modifying globals and exposing functions
|
|
||||||
into the QuickJS interpreter.
|
|
||||||
|
|
||||||
Each `QuickJSContext` instance has its own environment -- globals, built-in
|
|
||||||
classes -- and actions from one context won't leak into other contexts or
|
|
||||||
runtimes (with one exception, see [Asyncify][asyncify]).
|
|
||||||
|
|
||||||
Every context is created inside a
|
|
||||||
[QuickJSRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/QuickJSRuntime.md).
|
|
||||||
A runtime represents a Javascript heap, and you can even share values between
|
|
||||||
contexts in the same runtime.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
let state = 0
|
|
||||||
|
|
||||||
const fnHandle = vm.newFunction("nextId", () => {
|
|
||||||
return vm.newNumber(++state)
|
|
||||||
})
|
|
||||||
|
|
||||||
vm.setProp(vm.global, "nextId", fnHandle)
|
|
||||||
fnHandle.dispose()
|
|
||||||
|
|
||||||
const nextId = vm.unwrapResult(vm.evalCode(`nextId(); nextId(); nextId()`))
|
|
||||||
console.log("vm result:", vm.getNumber(nextId), "native state:", state)
|
|
||||||
|
|
||||||
nextId.dispose()
|
|
||||||
vm.dispose()
|
|
||||||
```
|
|
||||||
|
|
||||||
When you create a context from a top-level API like in the example above,
|
|
||||||
instead of by calling `runtime.newContext()`, a runtime is automatically created
|
|
||||||
for the lifetime of the context, and disposed of when you dispose the context.
|
|
||||||
|
|
||||||
#### Runtime
|
|
||||||
|
|
||||||
The runtime has APIs for CPU and memory limits that apply to all contexts within
|
|
||||||
the runtime in aggregate. You can also use the runtime to configure EcmaScript
|
|
||||||
module loading.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const runtime = QuickJS.newRuntime()
|
|
||||||
// "Should be enough for everyone" -- attributed to B. Gates
|
|
||||||
runtime.setMemoryLimit(1024 * 640)
|
|
||||||
// Limit stack size
|
|
||||||
runtime.setMaxStackSize(1024 * 320)
|
|
||||||
// Interrupt computation after 1024 calls to the interrupt handler
|
|
||||||
let interruptCycles = 0
|
|
||||||
runtime.setInterruptHandler(() => ++interruptCycles > 1024)
|
|
||||||
// Toy module system that always returns the module name
|
|
||||||
// as the default export
|
|
||||||
runtime.setModuleLoader((moduleName) => `export default '${moduleName}'`)
|
|
||||||
const context = runtime.newContext()
|
|
||||||
const ok = context.evalCode(`
|
|
||||||
import fooName from './foo.js'
|
|
||||||
globalThis.result = fooName
|
|
||||||
`)
|
|
||||||
context.unwrapResult(ok).dispose()
|
|
||||||
// logs "foo.js"
|
|
||||||
console.log(context.getProp(context.global, "result").consume(context.dump))
|
|
||||||
context.dispose()
|
|
||||||
runtime.dispose()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Memory Management
|
|
||||||
|
|
||||||
Many methods in this library return handles to memory allocated inside the
|
|
||||||
WebAssembly heap. These types cannot be garbage-collected as usual in
|
|
||||||
Javascript. Instead, you must manually manage their memory by calling a
|
|
||||||
`.dispose()` method to free the underlying resources. Once a handle has been
|
|
||||||
disposed, it cannot be used anymore. Note that in the example above, we call
|
|
||||||
`.dispose()` on each handle once it is no longer needed.
|
|
||||||
|
|
||||||
Calling `QuickJSContext.dispose()` will throw a RuntimeError if you've forgotten to
|
|
||||||
dispose any handles associated with that VM, so it's good practice to create a
|
|
||||||
new VM instance for each of your tests, and to call `vm.dispose()` at the end
|
|
||||||
of every test.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
const numberHandle = vm.newNumber(42)
|
|
||||||
// Note: numberHandle not disposed, so it leaks memory.
|
|
||||||
vm.dispose()
|
|
||||||
// throws RuntimeError: abort(Assertion failed: list_empty(&rt->gc_obj_list), at: quickjs/quickjs.c,1963,JS_FreeRuntime)
|
|
||||||
```
|
|
||||||
|
|
||||||
Here are some strategies to reduce the toil of calling `.dispose()` on each
|
|
||||||
handle you create:
|
|
||||||
|
|
||||||
#### Scope
|
|
||||||
|
|
||||||
A
|
|
||||||
[`Scope`](https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/scope.md#class-scope)
|
|
||||||
instance manages a set of disposables and calls their `.dispose()`
|
|
||||||
method in the reverse order in which they're added to the scope. Here's the
|
|
||||||
"Interfacing with the interpreter" example re-written using `Scope`:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
Scope.withScope((scope) => {
|
|
||||||
const vm = scope.manage(QuickJS.newContext())
|
|
||||||
let state = 0
|
|
||||||
|
|
||||||
const fnHandle = scope.manage(
|
|
||||||
vm.newFunction("nextId", () => {
|
|
||||||
return vm.newNumber(++state)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
vm.setProp(vm.global, "nextId", fnHandle)
|
|
||||||
|
|
||||||
const nextId = scope.manage(vm.unwrapResult(vm.evalCode(`nextId(); nextId(); nextId()`)))
|
|
||||||
console.log("vm result:", vm.getNumber(nextId), "native state:", state)
|
|
||||||
|
|
||||||
// When the withScope block exits, it calls scope.dispose(), which in turn calls
|
|
||||||
// the .dispose() methods of all the disposables managed by the scope.
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also create `Scope` instances with `new Scope()` if you want to manage
|
|
||||||
calling `scope.dispose()` yourself.
|
|
||||||
|
|
||||||
#### `Lifetime.consume(fn)`
|
|
||||||
|
|
||||||
[`Lifetime.consume`](https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/lifetime.md#consume)
|
|
||||||
is sugar for the common pattern of using a handle and then
|
|
||||||
immediately disposing of it. `Lifetime.consume` takes a `map` function that
|
|
||||||
produces a result of any type. The `map` fuction is called with the handle,
|
|
||||||
then the handle is disposed, then the result is returned.
|
|
||||||
|
|
||||||
Here's the "Interfacing with interpreter" example re-written using `.consume()`:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
let state = 0
|
|
||||||
|
|
||||||
vm.newFunction("nextId", () => {
|
|
||||||
return vm.newNumber(++state)
|
|
||||||
}).consume((fnHandle) => vm.setProp(vm.global, "nextId", fnHandle))
|
|
||||||
|
|
||||||
vm.unwrapResult(vm.evalCode(`nextId(); nextId(); nextId()`)).consume((nextId) =>
|
|
||||||
console.log("vm result:", vm.getNumber(nextId), "native state:", state)
|
|
||||||
)
|
|
||||||
|
|
||||||
vm.dispose()
|
|
||||||
```
|
|
||||||
|
|
||||||
Generally working with `Scope` leads to more straight-forward code, but
|
|
||||||
`Lifetime.consume` can be handy sugar as part of a method call chain.
|
|
||||||
|
|
||||||
### Exposing APIs
|
|
||||||
|
|
||||||
To add APIs inside the QuickJS environment, you'll need to create objects to
|
|
||||||
define the shape of your API, and add properties and functions to those objects
|
|
||||||
to allow code inside QuickJS to call code on the host.
|
|
||||||
|
|
||||||
By default, no host functionality is exposed to code running inside QuickJS.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
// `console.log`
|
|
||||||
const logHandle = vm.newFunction("log", (...args) => {
|
|
||||||
const nativeArgs = args.map(vm.dump)
|
|
||||||
console.log("QuickJS:", ...nativeArgs)
|
|
||||||
})
|
|
||||||
// Partially implement `console` object
|
|
||||||
const consoleHandle = vm.newObject()
|
|
||||||
vm.setProp(consoleHandle, "log", logHandle)
|
|
||||||
vm.setProp(vm.global, "console", consoleHandle)
|
|
||||||
consoleHandle.dispose()
|
|
||||||
logHandle.dispose()
|
|
||||||
|
|
||||||
vm.unwrapResult(vm.evalCode(`console.log("Hello from QuickJS!")`)).dispose()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Promises
|
|
||||||
|
|
||||||
To expose an asynchronous function that _returns a promise_ to callers within
|
|
||||||
QuickJS, your function can return the handle of a `QuickJSDeferredPromise`
|
|
||||||
created via `context.newPromise()`.
|
|
||||||
|
|
||||||
When you resolve a `QuickJSDeferredPromise` -- and generally whenever async
|
|
||||||
behavior completes for the VM -- pending listeners inside QuickJS may not
|
|
||||||
execute immediately. Your code needs to explicitly call
|
|
||||||
`runtime.executePendingJobs()` to resume execution inside QuickJS. This API
|
|
||||||
gives your code maximum control to _schedule_ when QuickJS will block the host's
|
|
||||||
event loop by resuming execution.
|
|
||||||
|
|
||||||
To work with QuickJS handles that contain a promise inside the environment, you
|
|
||||||
can convert the QuickJSHandle into a native promise using
|
|
||||||
`context.resolvePromise()`. Take care with this API to avoid 'deadlocks' where
|
|
||||||
the host awaits a guest promise, but the guest cannot make progress until the
|
|
||||||
host calls `runtime.executePendingJobs()`. The simplest way to avoid this kind
|
|
||||||
of deadlock is to always schedule `executePendingJobs` after any promise is
|
|
||||||
settled.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const vm = QuickJS.newContext()
|
|
||||||
const fakeFileSystem = new Map([["example.txt", "Example file content"]])
|
|
||||||
|
|
||||||
// Function that simulates reading data asynchronously
|
|
||||||
const readFileHandle = vm.newFunction("readFile", (pathHandle) => {
|
|
||||||
const path = vm.getString(pathHandle)
|
|
||||||
const promise = vm.newPromise()
|
|
||||||
setTimeout(() => {
|
|
||||||
const content = fakeFileSystem.get(path)
|
|
||||||
promise.resolve(vm.newString(content || ""))
|
|
||||||
}, 100)
|
|
||||||
// IMPORTANT: Once you resolve an async action inside QuickJS,
|
|
||||||
// call runtime.executePendingJobs() to run any code that was
|
|
||||||
// waiting on the promise or callback.
|
|
||||||
promise.settled.then(vm.runtime.executePendingJobs)
|
|
||||||
return promise.handle
|
|
||||||
})
|
|
||||||
readFileHandle.consume((handle) => vm.setProp(vm.global, "readFile", handle))
|
|
||||||
|
|
||||||
// Evaluate code that uses `readFile`, which returns a promise
|
|
||||||
const result = vm.evalCode(`(async () => {
|
|
||||||
const content = await readFile('example.txt')
|
|
||||||
return content.toUpperCase()
|
|
||||||
})()`)
|
|
||||||
const promiseHandle = vm.unwrapResult(result)
|
|
||||||
|
|
||||||
// Convert the promise handle into a native promise and await it.
|
|
||||||
// If code like this deadlocks, make sure you are calling
|
|
||||||
// runtime.executePendingJobs appropriately.
|
|
||||||
const resolvedResult = await vm.resolvePromise(promiseHandle)
|
|
||||||
promiseHandle.dispose()
|
|
||||||
const resolvedHandle = vm.unwrapResult(resolvedResult)
|
|
||||||
console.log("Result:", vm.getString(resolvedHandle))
|
|
||||||
resolvedHandle.dispose()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Asyncify
|
|
||||||
|
|
||||||
Sometimes, we want to create a function that's synchronous from the perspective
|
|
||||||
of QuickJS, but prefer to implement that function _asynchronously_ in your host
|
|
||||||
code. The most obvious use-case is for EcmaScript module loading. The underlying
|
|
||||||
QuickJS C library expects the module loader function to return synchronously,
|
|
||||||
but loading data synchronously in the browser or server is somewhere between "a
|
|
||||||
bad idea" and "impossible". QuickJS also doesn't expose an API to "pause" the
|
|
||||||
execution of a runtime, and adding such an API is tricky due to the VM's
|
|
||||||
implementation.
|
|
||||||
|
|
||||||
As a work-around, we provide an alternate build of QuickJS processed by
|
|
||||||
Emscripten/Binaryen's [ASYNCIFY](https://emscripten.org/docs/porting/asyncify.html)
|
|
||||||
compiler transform. Here's how Emscripten's documentation describes Asyncify:
|
|
||||||
|
|
||||||
> Asyncify lets synchronous C or C++ code interact with asynchronous \[host] JavaScript. This allows things like:
|
|
||||||
>
|
|
||||||
> - A synchronous call in C that yields to the event loop, which allows browser events to be handled.
|
|
||||||
>
|
|
||||||
> - A synchronous call in C that waits for an asynchronous operation in \[host] JS to complete.
|
|
||||||
>
|
|
||||||
> Asyncify automatically transforms ... code into a form that can be paused and
|
|
||||||
> resumed ..., so that it is asynchronous (hence the name “Asyncify”) even though
|
|
||||||
> \[it is written] in a normal synchronous way.
|
|
||||||
|
|
||||||
This means we can suspend an _entire WebAssembly module_ (which could contain
|
|
||||||
multiple runtimes and contexts) while our host Javascript loads data
|
|
||||||
asynchronously, and then resume execution once the data load completes. This is
|
|
||||||
a very handy superpower, but it comes with a couple of major limitations:
|
|
||||||
|
|
||||||
1. _An asyncified WebAssembly module can only suspend to wait for a single
|
|
||||||
asynchronous call at a time_. You may call back into a suspended WebAssembly
|
|
||||||
module eg. to create a QuickJS value to return a result, but the system will
|
|
||||||
crash if this call tries to suspend again. Take a look at Emscripten's documentation
|
|
||||||
on [reentrancy](https://emscripten.org/docs/porting/asyncify.html#reentrancy).
|
|
||||||
|
|
||||||
2. _Asyncified code is bigger and runs slower_. The asyncified build of
|
|
||||||
Quickjs-emscripten library is 1M, 2x larger than the 500K of the default
|
|
||||||
version. There may be room for further
|
|
||||||
[optimization](https://emscripten.org/docs/porting/asyncify.html#optimizing)
|
|
||||||
Of our build in the future.
|
|
||||||
|
|
||||||
To use asyncify features, use the following functions:
|
|
||||||
|
|
||||||
- [newAsyncRuntime][]: create a runtime inside a new WebAssembly module.
|
|
||||||
- [newAsyncContext][]: create runtime and context together inside a new
|
|
||||||
WebAssembly module.
|
|
||||||
- [newQuickJSAsyncWASMModule][]: create an empty WebAssembly module.
|
|
||||||
|
|
||||||
[newasyncruntime]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/modules.md#newasyncruntime
|
|
||||||
[newasynccontext]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/modules.md#newasynccontext
|
|
||||||
[newquickjsasyncwasmmodule]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/modules.md#newquickjsasyncwasmmodule
|
|
||||||
|
|
||||||
These functions are asynchronous because they always create a new underlying
|
|
||||||
WebAssembly module so that each instance can suspend and resume independently,
|
|
||||||
and instantiating a WebAssembly module is an async operation. This also adds
|
|
||||||
substantial overhead compared to creating a runtime or context inside an
|
|
||||||
existing module; if you only need to wait for a single async action at a time,
|
|
||||||
you can create a single top-level module and create runtimes or contexts inside
|
|
||||||
of it.
|
|
||||||
|
|
||||||
##### Async module loader
|
|
||||||
|
|
||||||
Here's an example of valuating a script that loads React asynchronously as an ES
|
|
||||||
module. In our example, we're loading from the filesystem for reproducibility,
|
|
||||||
but you can use this technique to load using `fetch`.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const module = await newQuickJSAsyncWASMModule()
|
|
||||||
const runtime = module.newRuntime()
|
|
||||||
const path = await import("path")
|
|
||||||
const { promises: fs } = await import("fs")
|
|
||||||
|
|
||||||
const importsPath = path.join(__dirname, "../examples/imports") + "/"
|
|
||||||
// Module loaders can return promises.
|
|
||||||
// Execution will suspend until the promise resolves.
|
|
||||||
runtime.setModuleLoader((moduleName) => {
|
|
||||||
const modulePath = path.join(importsPath, moduleName)
|
|
||||||
if (!modulePath.startsWith(importsPath)) {
|
|
||||||
throw new Error("out of bounds")
|
|
||||||
}
|
|
||||||
console.log("loading", moduleName, "from", modulePath)
|
|
||||||
return fs.readFile(modulePath, "utf-8")
|
|
||||||
})
|
|
||||||
|
|
||||||
// evalCodeAsync is required when execution may suspend.
|
|
||||||
const context = runtime.newContext()
|
|
||||||
const result = await context.evalCodeAsync(`
|
|
||||||
import * as React from 'esm.sh/react@17'
|
|
||||||
import * as ReactDOMServer from 'esm.sh/react-dom@17/server'
|
|
||||||
const e = React.createElement
|
|
||||||
globalThis.html = ReactDOMServer.renderToStaticMarkup(
|
|
||||||
e('div', null, e('strong', null, 'Hello world!'))
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
context.unwrapResult(result).dispose()
|
|
||||||
const html = context.getProp(context.global, "html").consume(context.getString)
|
|
||||||
console.log(html) // <div><strong>Hello world!</strong></div>
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Async on host, sync in QuickJS
|
|
||||||
|
|
||||||
Here's an example of turning an async function into a sync function inside the
|
|
||||||
VM.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const context = await newAsyncContext()
|
|
||||||
const path = await import("path")
|
|
||||||
const { promises: fs } = await import("fs")
|
|
||||||
|
|
||||||
const importsPath = path.join(__dirname, "../examples/imports") + "/"
|
|
||||||
const readFileHandle = context.newAsyncifiedFunction("readFile", async (pathHandle) => {
|
|
||||||
const pathString = path.join(importsPath, context.getString(pathHandle))
|
|
||||||
if (!pathString.startsWith(importsPath)) {
|
|
||||||
throw new Error("out of bounds")
|
|
||||||
}
|
|
||||||
const data = await fs.readFile(pathString, "utf-8")
|
|
||||||
return context.newString(data)
|
|
||||||
})
|
|
||||||
readFileHandle.consume((fn) => context.setProp(context.global, "readFile", fn))
|
|
||||||
|
|
||||||
// evalCodeAsync is required when execution may suspend.
|
|
||||||
const result = await context.evalCodeAsync(`
|
|
||||||
// Not a promise! Sync! vvvvvvvvvvvvvvvvvvvv
|
|
||||||
const data = JSON.parse(readFile('data.json'))
|
|
||||||
data.map(x => x.toUpperCase()).join(' ')
|
|
||||||
`)
|
|
||||||
const upperCaseData = context.unwrapResult(result).consume(context.getString)
|
|
||||||
console.log(upperCaseData) // 'VERY USEFUL DATA'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing your code
|
|
||||||
|
|
||||||
This library is complicated to use, so please consider automated testing your
|
|
||||||
implementation. We highly writing your test suite to run with both the "release"
|
|
||||||
build variant of quickjs-emscripten, and also the [DEBUG_SYNC] build variant.
|
|
||||||
The debug sync build variant has extra instrumentation code for detecting memory
|
|
||||||
leaks.
|
|
||||||
|
|
||||||
The class [TestQuickJSWASMModule] exposes the memory leak detection API, although
|
|
||||||
this API is only accurate when using `DEBUG_SYNC` variant.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Define your test suite in a function, so that you can test against
|
|
||||||
// different module loaders.
|
|
||||||
function myTests(moduleLoader: () => Promise<QuickJSWASMModule>) {
|
|
||||||
let QuickJS: TestQuickJSWASMModule
|
|
||||||
beforeEach(async () => {
|
|
||||||
// Get a unique TestQuickJSWASMModule instance for each test.
|
|
||||||
const wasmModule = await moduleLoader()
|
|
||||||
QuickJS = new TestQuickJSWASMModule(wasmModule)
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
// Assert that the test disposed all handles. The DEBUG_SYNC build
|
|
||||||
// variant will show detailed traces for each leak.
|
|
||||||
QuickJS.assertNoMemoryAllocated()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("works well", () => {
|
|
||||||
// TODO: write a test using QuickJS
|
|
||||||
const context = QuickJS.newContext()
|
|
||||||
context.unwrapResult(context.evalCode("1 + 1")).dispose()
|
|
||||||
context.dispose()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the test suite against a matrix of module loaders.
|
|
||||||
describe("Check for memory leaks with QuickJS DEBUG build", () => {
|
|
||||||
const moduleLoader = memoizePromiseFactory(() => newQuickJSWASMModule(DEBUG_SYNC))
|
|
||||||
myTests(moduleLoader)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Realistic test with QuickJS RELEASE build", () => {
|
|
||||||
myTests(getQuickJS)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
For more testing examples, please explore the typescript source of [quickjs-emscripten][ts] repository.
|
|
||||||
|
|
||||||
[ts]: https://github.com/justjake/quickjs-emscripten/blob/main/ts
|
|
||||||
[debug_sync]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/modules.md#debug_sync
|
|
||||||
[testquickjswasmmodule]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/classes/TestQuickJSWASMModule.md
|
|
||||||
|
|
||||||
### Debugging
|
|
||||||
|
|
||||||
- Switch to a DEBUG build variant of the WebAssembly module to see debug log messages from the C part of this library.
|
|
||||||
- Set `process.env.QTS_DEBUG` to see debug log messages from the Javascript part of this library.
|
|
||||||
|
|
||||||
### More Documentation
|
|
||||||
|
|
||||||
[Github] | [NPM] | [API Documentation][api] | [Examples][tests]
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
This was inspired by seeing https://github.com/maple3142/duktape-eval
|
|
||||||
[on Hacker News](https://news.ycombinator.com/item?id=21946565) and Figma's
|
|
||||||
blogposts about using building a Javascript plugin runtime:
|
|
||||||
|
|
||||||
- [How Figma built the Figma plugin system](https://www.figma.com/blog/how-we-built-the-figma-plugin-system/): Describes the LowLevelJavascriptVm interface.
|
|
||||||
- [An update on plugin security](https://www.figma.com/blog/an-update-on-plugin-security/): Figma switches to QuickJS.
|
|
||||||
|
|
||||||
## Status & Roadmap
|
|
||||||
|
|
||||||
**Stability**: Because the version number of this project is below `1.0.0`,
|
|
||||||
\*expect occasional breaking API changes.
|
|
||||||
|
|
||||||
**Security**: This project makes every effort to be secure, but has not been
|
|
||||||
audited. Please use with care in production settings.
|
|
||||||
|
|
||||||
**Roadmap**: I work on this project in my free time, for fun. Here's I'm
|
|
||||||
thinking comes next. Last updated 2022-03-18.
|
|
||||||
|
|
||||||
1. Further work on module loading APIs:
|
|
||||||
|
|
||||||
- Create modules via Javascript, instead of source text.
|
|
||||||
- Scan source text for imports, for ahead of time or concurrent loading.
|
|
||||||
(This is possible with third-party tools, so lower priority.)
|
|
||||||
|
|
||||||
2. Higher-level tools for reading QuickJS values:
|
|
||||||
|
|
||||||
- Type guard functions: `context.isArray(handle)`, `context.isPromise(handle)`, etc.
|
|
||||||
- Iteration utilities: `context.getIterable(handle)`, `context.iterateObjectEntries(handle)`.
|
|
||||||
This better supports user-level code to deserialize complex handle objects.
|
|
||||||
|
|
||||||
3. Higher-level tools for creating QuickJS values:
|
|
||||||
|
|
||||||
- Devise a way to avoid needing to mess around with handles when setting up
|
|
||||||
the environment.
|
|
||||||
- Consider integrating
|
|
||||||
[quickjs-emscripten-sync](https://github.com/reearth/quickjs-emscripten-sync)
|
|
||||||
for automatic translation.
|
|
||||||
- Consider class-based or interface-type-based marshalling.
|
|
||||||
|
|
||||||
4. EcmaScript Modules / WebAssembly files / Deno support. This requires me to
|
|
||||||
learn a lot of new things, but should be interesting for modern browser usage.
|
|
||||||
|
|
||||||
5. SQLite integration.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- Duktape wrapped in Wasm: https://github.com/maple3142/duktape-eval/blob/main/src/Makefile
|
|
||||||
- QuickJS wrapped in C++: https://github.com/ftk/quickjspp
|
|
||||||
|
|
||||||
## Developing
|
|
||||||
|
|
||||||
This library is implemented in two languages: C (compiled to WASM with
|
|
||||||
Emscripten), and Typescript.
|
|
||||||
|
|
||||||
### The C parts
|
|
||||||
|
|
||||||
The ./c directory contains C code that wraps the QuickJS C library (in ./quickjs).
|
|
||||||
Public functions (those starting with `QTS_`) in ./c/interface.c are
|
|
||||||
automatically exported to native code (via a generated header) and to
|
|
||||||
Typescript (via a generated FFI class). See ./generate.ts for how this works.
|
|
||||||
|
|
||||||
The C code builds as both with `emscripten` (using `emcc`), to produce WASM (or
|
|
||||||
ASM.js) and with `clang`. Build outputs are checked in, so you can iterate on
|
|
||||||
the Javascript parts of the library without setting up the Emscripten toolchain.
|
|
||||||
|
|
||||||
Intermediate object files from QuickJS end up in ./build/quickjs/.
|
|
||||||
|
|
||||||
This project uses `emscripten 3.1.32`.
|
|
||||||
|
|
||||||
- On ARM64, you should install `emscripten` on your machine. For example on macOS, `brew install emscripten`.
|
|
||||||
- If _the correct version of emcc_ is not in your PATH, compilation falls back to using Docker.
|
|
||||||
On ARM64, this is 10-50x slower than native compilation, but it's just fine on x64.
|
|
||||||
|
|
||||||
Related NPM scripts:
|
|
||||||
|
|
||||||
- `yarn update-quickjs` will sync the ./quickjs folder with a
|
|
||||||
github repo tracking the upstream QuickJS.
|
|
||||||
- `yarn make-debug` will rebuild C outputs into ./build/wrapper
|
|
||||||
- `yarn make-release` will rebuild C outputs in release mode, which is the mode
|
|
||||||
that should be checked into the repo.
|
|
||||||
|
|
||||||
### The Typescript parts
|
|
||||||
|
|
||||||
The ./ts directory contains Typescript types and wraps the generated Emscripten
|
|
||||||
FFI in a more usable interface.
|
|
||||||
|
|
||||||
You'll need `node` and `yarn`. Install dependencies with `yarn install`.
|
|
||||||
|
|
||||||
- `yarn build` produces ./dist.
|
|
||||||
- `yarn test` runs the tests.
|
|
||||||
- `yarn test --watch` watches for changes and re-runs the tests.
|
|
||||||
|
|
||||||
### Yarn updates
|
|
||||||
|
|
||||||
Just run `yarn set version from sources` to upgrade the Yarn release.
|
|
||||||
819
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/c/interface.c
generated
vendored
819
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/c/interface.c
generated
vendored
@@ -1,819 +0,0 @@
|
|||||||
/**
|
|
||||||
* interface.c
|
|
||||||
*
|
|
||||||
* We primarily use JSValue* (pointer to JSValue) when communicating with the
|
|
||||||
* host javascript environment, because pointers are trivial to use for calls
|
|
||||||
* into emscripten because they're just a number!
|
|
||||||
*
|
|
||||||
* As with the quickjs.h API, a JSValueConst* value is "borrowed" and should
|
|
||||||
* not be freed. A JSValue* is "owned" and should be freed by the owner.
|
|
||||||
*
|
|
||||||
* Functions starting with "QTS_" are exported by generate.ts to:
|
|
||||||
* - interface.h for native C code.
|
|
||||||
* - ffi.ts for emscripten.
|
|
||||||
*
|
|
||||||
* We support building the following build outputs:
|
|
||||||
*
|
|
||||||
* ## 1. Native machine code
|
|
||||||
* For internal development testing purposes.
|
|
||||||
*
|
|
||||||
* ## 2. WASM via Emscripten
|
|
||||||
* For general production use.
|
|
||||||
*
|
|
||||||
* ## 3. Experimental: Asyncified WASM via Emscripten with -s ASYNCIFY=1.
|
|
||||||
* This variant supports treating async host Javascript calls as synchronous
|
|
||||||
* from the perspective of the WASM c code.
|
|
||||||
*
|
|
||||||
* The way this works is described here:
|
|
||||||
* https://emscripten.org/docs/porting/asyncify.html
|
|
||||||
*
|
|
||||||
* In this variant, any call into our C code could return a promise if it ended
|
|
||||||
* up suspended. We mark the methods we suspect might suspend due to users' code
|
|
||||||
* as returning MaybeAsync(T). This information is ignored for the regular
|
|
||||||
* build.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
#include <emscripten.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <math.h> // For NAN
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#ifdef QTS_SANITIZE_LEAK
|
|
||||||
#include <sanitizer/lsan_interface.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../quickjs/cutils.h"
|
|
||||||
#include "../quickjs/quickjs-libc.h"
|
|
||||||
#include "../quickjs/quickjs.h"
|
|
||||||
|
|
||||||
#define PKG "quickjs-emscripten: "
|
|
||||||
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
#define QTS_DEBUG(msg) qts_log(msg);
|
|
||||||
#define QTS_DUMP(value) qts_dump(ctx, value);
|
|
||||||
#else
|
|
||||||
#define QTS_DEBUG(msg) ;
|
|
||||||
#define QTS_DUMP(value) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal to our FFI code generator that this string argument should be passed as a pointer
|
|
||||||
* allocated by the caller on the heap, not a JS string on the stack.
|
|
||||||
* https://github.com/emscripten-core/emscripten/issues/6860#issuecomment-405818401
|
|
||||||
*/
|
|
||||||
#define BorrowedHeapChar const char
|
|
||||||
#define OwnedHeapChar char
|
|
||||||
#define JSBorrowedChar const char
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal to our FFI code generator that this function should be called
|
|
||||||
* asynchronously when compiled with ASYNCIFY.
|
|
||||||
*/
|
|
||||||
#define MaybeAsync(T) T
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal to our FFI code generator that this function is only available in
|
|
||||||
* ASYNCIFY builds.
|
|
||||||
*/
|
|
||||||
#define AsyncifyOnly(T) T
|
|
||||||
|
|
||||||
#define JSVoid void
|
|
||||||
|
|
||||||
#define EvalFlags int
|
|
||||||
#define EvalDetectModule int
|
|
||||||
|
|
||||||
void qts_log(char *msg) {
|
|
||||||
fputs(PKG, stderr);
|
|
||||||
fputs(msg, stderr);
|
|
||||||
fputs("\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void qts_dump(JSContext *ctx, JSValueConst value) {
|
|
||||||
const char *str = JS_ToCString(ctx, value);
|
|
||||||
if (!str) {
|
|
||||||
QTS_DEBUG("QTS_DUMP: can't dump");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fputs(str, stderr);
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_prop_if_needed(JSContext *ctx, JSValueConst dest, JSValueConst src, const char *prop_name) {
|
|
||||||
JSAtom prop_atom = JS_NewAtom(ctx, prop_name);
|
|
||||||
JSValue dest_prop = JS_GetProperty(ctx, dest, prop_atom);
|
|
||||||
if (JS_IsUndefined(dest_prop)) {
|
|
||||||
JSValue src_prop = JS_GetProperty(ctx, src, prop_atom);
|
|
||||||
if (!JS_IsUndefined(src_prop) && !JS_IsException(src_prop)) {
|
|
||||||
JS_SetProperty(ctx, dest, prop_atom, src_prop);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
JS_FreeValue(ctx, dest_prop);
|
|
||||||
}
|
|
||||||
JS_FreeAtom(ctx, prop_atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *jsvalue_to_heap(JSValueConst value) {
|
|
||||||
JSValue *result = malloc(sizeof(JSValue));
|
|
||||||
if (result) {
|
|
||||||
// Could be better optimized, but at -0z / -ftlo, it
|
|
||||||
// appears to produce the same binary code as a memcpy.
|
|
||||||
*result = value;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_Throw(JSContext *ctx, JSValueConst *error) {
|
|
||||||
JSValue copy = JS_DupValue(ctx, *error);
|
|
||||||
return jsvalue_to_heap(JS_Throw(ctx, copy));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewError(JSContext *ctx) {
|
|
||||||
return jsvalue_to_heap(JS_NewError(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Limits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory limit. Set to -1 to disable.
|
|
||||||
*/
|
|
||||||
void QTS_RuntimeSetMemoryLimit(JSRuntime *rt, size_t limit) {
|
|
||||||
JS_SetMemoryLimit(rt, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory diagnostics
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSValue *QTS_RuntimeComputeMemoryUsage(JSRuntime *rt, JSContext *ctx) {
|
|
||||||
JSMemoryUsage s;
|
|
||||||
JS_ComputeMemoryUsage(rt, &s);
|
|
||||||
|
|
||||||
// Note that we're going to allocate more memory just to report the memory usage.
|
|
||||||
// A more sound approach would be to bind JSMemoryUsage struct directly - but that's
|
|
||||||
// a lot of work. This should be okay in the mean time.
|
|
||||||
JSValue result = JS_NewObject(ctx);
|
|
||||||
|
|
||||||
// Manually generated via editor-fu from JSMemoryUsage struct definition in quickjs.h
|
|
||||||
JS_SetPropertyStr(ctx, result, "malloc_limit", JS_NewInt64(ctx, s.malloc_limit));
|
|
||||||
JS_SetPropertyStr(ctx, result, "memory_used_size", JS_NewInt64(ctx, s.memory_used_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "malloc_count", JS_NewInt64(ctx, s.malloc_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "memory_used_count", JS_NewInt64(ctx, s.memory_used_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "atom_count", JS_NewInt64(ctx, s.atom_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "atom_size", JS_NewInt64(ctx, s.atom_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "str_count", JS_NewInt64(ctx, s.str_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "str_size", JS_NewInt64(ctx, s.str_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "obj_count", JS_NewInt64(ctx, s.obj_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "obj_size", JS_NewInt64(ctx, s.obj_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "prop_count", JS_NewInt64(ctx, s.prop_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "prop_size", JS_NewInt64(ctx, s.prop_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "shape_count", JS_NewInt64(ctx, s.shape_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "shape_size", JS_NewInt64(ctx, s.shape_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "js_func_count", JS_NewInt64(ctx, s.js_func_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "js_func_size", JS_NewInt64(ctx, s.js_func_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "js_func_code_size", JS_NewInt64(ctx, s.js_func_code_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "js_func_pc2line_count", JS_NewInt64(ctx, s.js_func_pc2line_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "js_func_pc2line_size", JS_NewInt64(ctx, s.js_func_pc2line_size));
|
|
||||||
JS_SetPropertyStr(ctx, result, "c_func_count", JS_NewInt64(ctx, s.c_func_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "array_count", JS_NewInt64(ctx, s.array_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "fast_array_count", JS_NewInt64(ctx, s.fast_array_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "fast_array_elements", JS_NewInt64(ctx, s.fast_array_elements));
|
|
||||||
JS_SetPropertyStr(ctx, result, "binary_object_count", JS_NewInt64(ctx, s.binary_object_count));
|
|
||||||
JS_SetPropertyStr(ctx, result, "binary_object_size", JS_NewInt64(ctx, s.binary_object_size));
|
|
||||||
|
|
||||||
return jsvalue_to_heap(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnedHeapChar *QTS_RuntimeDumpMemoryUsage(JSRuntime *rt) {
|
|
||||||
char *result = malloc(sizeof(char) * 1024);
|
|
||||||
FILE *memfile = fmemopen(result, 1024, "w");
|
|
||||||
JSMemoryUsage s;
|
|
||||||
JS_ComputeMemoryUsage(rt, &s);
|
|
||||||
JS_DumpMemoryUsage(memfile, &s, rt);
|
|
||||||
fclose(memfile);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_RecoverableLeakCheck() {
|
|
||||||
#ifdef QTS_SANITIZE_LEAK
|
|
||||||
return __lsan_do_recoverable_leak_check();
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_BuildIsSanitizeLeak() {
|
|
||||||
#ifdef QTS_SANITIZE_LEAK
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
EM_JS(void, set_asyncify_stack_size, (size_t size), {
|
|
||||||
Asyncify.StackSize = size || 81920;
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the stack size limit, in bytes. Set to 0 to disable.
|
|
||||||
*/
|
|
||||||
void QTS_RuntimeSetMaxStackSize(JSRuntime *rt, size_t stack_size) {
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
set_asyncify_stack_size(stack_size);
|
|
||||||
#endif
|
|
||||||
JS_SetMaxStackSize(rt, stack_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant pointers. Because we always use JSValue* from the host Javascript environment,
|
|
||||||
* we need helper fuctions to return pointers to these constants.
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSValueConst QTS_Undefined = JS_UNDEFINED;
|
|
||||||
JSValueConst *QTS_GetUndefined() {
|
|
||||||
return &QTS_Undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValueConst QTS_Null = JS_NULL;
|
|
||||||
JSValueConst *QTS_GetNull() {
|
|
||||||
return &QTS_Null;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValueConst QTS_False = JS_FALSE;
|
|
||||||
JSValueConst *QTS_GetFalse() {
|
|
||||||
return &QTS_False;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValueConst QTS_True = JS_TRUE;
|
|
||||||
JSValueConst *QTS_GetTrue() {
|
|
||||||
return &QTS_True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard FFI functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSRuntime *QTS_NewRuntime() {
|
|
||||||
return JS_NewRuntime();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeRuntime(JSRuntime *rt) {
|
|
||||||
JS_FreeRuntime(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSContext *QTS_NewContext(JSRuntime *rt) {
|
|
||||||
return JS_NewContext(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeContext(JSContext *ctx) {
|
|
||||||
JS_FreeContext(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeValuePointer(JSContext *ctx, JSValue *value) {
|
|
||||||
JS_FreeValue(ctx, *value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeValuePointerRuntime(JSRuntime *rt, JSValue *value) {
|
|
||||||
JS_FreeValueRT(rt, *value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeVoidPointer(JSContext *ctx, JSVoid *ptr) {
|
|
||||||
js_free(ctx, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_FreeCString(JSContext *ctx, JSBorrowedChar *str) {
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_DupValuePointer(JSContext *ctx, JSValueConst *val) {
|
|
||||||
return jsvalue_to_heap(JS_DupValue(ctx, *val));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewObject(JSContext *ctx) {
|
|
||||||
return jsvalue_to_heap(JS_NewObject(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewObjectProto(JSContext *ctx, JSValueConst *proto) {
|
|
||||||
return jsvalue_to_heap(JS_NewObjectProto(ctx, *proto));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewArray(JSContext *ctx) {
|
|
||||||
return jsvalue_to_heap(JS_NewArray(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewFloat64(JSContext *ctx, double num) {
|
|
||||||
return jsvalue_to_heap(JS_NewFloat64(ctx, num));
|
|
||||||
}
|
|
||||||
|
|
||||||
double QTS_GetFloat64(JSContext *ctx, JSValueConst *value) {
|
|
||||||
double result = NAN;
|
|
||||||
JS_ToFloat64(ctx, &result, *value);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewString(JSContext *ctx, BorrowedHeapChar *string) {
|
|
||||||
return jsvalue_to_heap(JS_NewString(ctx, string));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSBorrowedChar *QTS_GetString(JSContext *ctx, JSValueConst *value) {
|
|
||||||
return JS_ToCString(ctx, *value);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue qts_get_symbol_key(JSContext *ctx, JSValueConst *value) {
|
|
||||||
JSValue global = JS_GetGlobalObject(ctx);
|
|
||||||
JSValue Symbol = JS_GetPropertyStr(ctx, global, "Symbol");
|
|
||||||
JS_FreeValue(ctx, global);
|
|
||||||
|
|
||||||
JSValue Symbol_keyFor = JS_GetPropertyStr(ctx, Symbol, "keyFor");
|
|
||||||
JSValue key = JS_Call(ctx, Symbol_keyFor, Symbol, 1, value);
|
|
||||||
JS_FreeValue(ctx, Symbol_keyFor);
|
|
||||||
JS_FreeValue(ctx, Symbol);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewSymbol(JSContext *ctx, BorrowedHeapChar *description, int isGlobal) {
|
|
||||||
JSValue global = JS_GetGlobalObject(ctx);
|
|
||||||
JSValue Symbol = JS_GetPropertyStr(ctx, global, "Symbol");
|
|
||||||
JS_FreeValue(ctx, global);
|
|
||||||
JSValue descriptionValue = JS_NewString(ctx, description);
|
|
||||||
JSValue symbol;
|
|
||||||
|
|
||||||
if (isGlobal != 0) {
|
|
||||||
JSValue Symbol_for = JS_GetPropertyStr(ctx, Symbol, "for");
|
|
||||||
symbol = JS_Call(ctx, Symbol_for, Symbol, 1, &descriptionValue);
|
|
||||||
JS_FreeValue(ctx, descriptionValue);
|
|
||||||
JS_FreeValue(ctx, Symbol_for);
|
|
||||||
JS_FreeValue(ctx, Symbol);
|
|
||||||
return jsvalue_to_heap(symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
symbol = JS_Call(ctx, Symbol, JS_UNDEFINED, 1, &descriptionValue);
|
|
||||||
JS_FreeValue(ctx, descriptionValue);
|
|
||||||
JS_FreeValue(ctx, Symbol);
|
|
||||||
|
|
||||||
return jsvalue_to_heap(symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(JSBorrowedChar *) QTS_GetSymbolDescriptionOrKey(JSContext *ctx, JSValueConst *value) {
|
|
||||||
JSBorrowedChar *result;
|
|
||||||
|
|
||||||
JSValue key = qts_get_symbol_key(ctx, value);
|
|
||||||
if (!JS_IsUndefined(key)) {
|
|
||||||
result = JS_ToCString(ctx, key);
|
|
||||||
JS_FreeValue(ctx, key);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue description = JS_GetPropertyStr(ctx, *value, "description");
|
|
||||||
result = JS_ToCString(ctx, description);
|
|
||||||
JS_FreeValue(ctx, description);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_IsGlobalSymbol(JSContext *ctx, JSValueConst *value) {
|
|
||||||
JSValue key = qts_get_symbol_key(ctx, value);
|
|
||||||
int undefined = JS_IsUndefined(key);
|
|
||||||
JS_FreeValue(ctx, key);
|
|
||||||
|
|
||||||
if (undefined) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_IsJobPending(JSRuntime *rt) {
|
|
||||||
return JS_IsJobPending(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
runs pending jobs (Promises/async functions) until it encounters
|
|
||||||
an exception or it executed the passed maxJobsToExecute jobs.
|
|
||||||
|
|
||||||
Passing a negative value will run the loop until there are no more
|
|
||||||
pending jobs or an exception happened
|
|
||||||
|
|
||||||
Returns the executed number of jobs or the exception encountered
|
|
||||||
*/
|
|
||||||
MaybeAsync(JSValue *) QTS_ExecutePendingJob(JSRuntime *rt, int maxJobsToExecute, JSContext **lastJobContext) {
|
|
||||||
JSContext *pctx;
|
|
||||||
int status = 1;
|
|
||||||
int executed = 0;
|
|
||||||
while (executed != maxJobsToExecute && status == 1) {
|
|
||||||
status = JS_ExecutePendingJob(rt, &pctx);
|
|
||||||
if (status == -1) {
|
|
||||||
*lastJobContext = pctx;
|
|
||||||
return jsvalue_to_heap(JS_GetException(pctx));
|
|
||||||
} else if (status == 1) {
|
|
||||||
*lastJobContext = pctx;
|
|
||||||
executed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
char msg[500];
|
|
||||||
sprintf(msg, "QTS_ExecutePendingJob(executed: %d, pctx: %p, lastJobExecuted: %p)", executed, pctx, *lastJobContext);
|
|
||||||
QTS_DEBUG(msg)
|
|
||||||
#endif
|
|
||||||
return jsvalue_to_heap(JS_NewFloat64(pctx, executed));
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(JSValue *) QTS_GetProp(JSContext *ctx, JSValueConst *this_val, JSValueConst *prop_name) {
|
|
||||||
JSAtom prop_atom = JS_ValueToAtom(ctx, *prop_name);
|
|
||||||
JSValue prop_val = JS_GetProperty(ctx, *this_val, prop_atom);
|
|
||||||
JS_FreeAtom(ctx, prop_atom);
|
|
||||||
return jsvalue_to_heap(prop_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(void) QTS_SetProp(JSContext *ctx, JSValueConst *this_val, JSValueConst *prop_name, JSValueConst *prop_value) {
|
|
||||||
JSAtom prop_atom = JS_ValueToAtom(ctx, *prop_name);
|
|
||||||
JSValue extra_prop_value = JS_DupValue(ctx, *prop_value);
|
|
||||||
// TODO: should we use DefineProperty internally if this object doesn't have the property yet?
|
|
||||||
JS_SetProperty(ctx, *this_val, prop_atom, extra_prop_value); // consumes extra_prop_value
|
|
||||||
JS_FreeAtom(ctx, prop_atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_DefineProp(JSContext *ctx, JSValueConst *this_val, JSValueConst *prop_name, JSValueConst *prop_value, JSValueConst *get, JSValueConst *set, bool configurable, bool enumerable, bool has_value) {
|
|
||||||
JSAtom prop_atom = JS_ValueToAtom(ctx, *prop_name);
|
|
||||||
|
|
||||||
int flags = 0;
|
|
||||||
if (configurable) {
|
|
||||||
flags = flags | JS_PROP_CONFIGURABLE;
|
|
||||||
if (has_value) {
|
|
||||||
flags = flags | JS_PROP_HAS_CONFIGURABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (enumerable) {
|
|
||||||
flags = flags | JS_PROP_ENUMERABLE;
|
|
||||||
if (has_value) {
|
|
||||||
flags = flags | JS_PROP_HAS_ENUMERABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!JS_IsUndefined(*get)) {
|
|
||||||
flags = flags | JS_PROP_HAS_GET;
|
|
||||||
}
|
|
||||||
if (!JS_IsUndefined(*set)) {
|
|
||||||
flags = flags | JS_PROP_HAS_SET;
|
|
||||||
}
|
|
||||||
if (has_value) {
|
|
||||||
flags = flags | JS_PROP_HAS_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_DefineProperty(ctx, *this_val, prop_atom, *prop_value, *get, *set, flags);
|
|
||||||
JS_FreeAtom(ctx, prop_atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(JSValue *) QTS_Call(JSContext *ctx, JSValueConst *func_obj, JSValueConst *this_obj, int argc, JSValueConst **argv_ptrs) {
|
|
||||||
// convert array of pointers to array of values
|
|
||||||
JSValueConst argv[argc];
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
argv[i] = *(argv_ptrs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsvalue_to_heap(JS_Call(ctx, *func_obj, *this_obj, argc, argv));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If maybe_exception is an exception, get the error.
|
|
||||||
* Otherwise, return NULL.
|
|
||||||
*/
|
|
||||||
JSValue *QTS_ResolveException(JSContext *ctx, JSValue *maybe_exception) {
|
|
||||||
if (JS_IsException(*maybe_exception)) {
|
|
||||||
return jsvalue_to_heap(JS_GetException(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(JSBorrowedChar *) QTS_Dump(JSContext *ctx, JSValueConst *obj) {
|
|
||||||
JSValue obj_json_value = JS_JSONStringify(ctx, *obj, JS_UNDEFINED, JS_UNDEFINED);
|
|
||||||
if (!JS_IsException(obj_json_value)) {
|
|
||||||
const char *obj_json_chars = JS_ToCString(ctx, obj_json_value);
|
|
||||||
JS_FreeValue(ctx, obj_json_value);
|
|
||||||
if (obj_json_chars != NULL) {
|
|
||||||
JSValue enumerable_props = JS_ParseJSON(ctx, obj_json_chars, strlen(obj_json_chars), "<dump>");
|
|
||||||
JS_FreeCString(ctx, obj_json_chars);
|
|
||||||
if (!JS_IsException(enumerable_props)) {
|
|
||||||
// Copy common non-enumerable props for different object types.
|
|
||||||
// Errors:
|
|
||||||
copy_prop_if_needed(ctx, enumerable_props, *obj, "name");
|
|
||||||
copy_prop_if_needed(ctx, enumerable_props, *obj, "message");
|
|
||||||
copy_prop_if_needed(ctx, enumerable_props, *obj, "stack");
|
|
||||||
|
|
||||||
// Serialize again.
|
|
||||||
JSValue enumerable_json = JS_JSONStringify(ctx, enumerable_props, JS_UNDEFINED, JS_UNDEFINED);
|
|
||||||
JS_FreeValue(ctx, enumerable_props);
|
|
||||||
|
|
||||||
JSBorrowedChar *result = QTS_GetString(ctx, &enumerable_json);
|
|
||||||
JS_FreeValue(ctx, enumerable_json);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
qts_log("Error dumping JSON:");
|
|
||||||
js_std_dump_error(ctx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fallback: convert to string
|
|
||||||
return QTS_GetString(ctx, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeAsync(JSValue *) QTS_Eval(JSContext *ctx, BorrowedHeapChar *js_code, const char *filename, EvalDetectModule detectModule, EvalFlags evalFlags) {
|
|
||||||
size_t js_code_len = strlen(js_code);
|
|
||||||
|
|
||||||
if (detectModule) {
|
|
||||||
if (JS_DetectModule((const char *)js_code, js_code_len)) {
|
|
||||||
QTS_DEBUG("QTS_Eval: Detected module = true");
|
|
||||||
evalFlags |= JS_EVAL_TYPE_MODULE;
|
|
||||||
} else {
|
|
||||||
QTS_DEBUG("QTS_Eval: Detected module = false");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QTS_DEBUG("QTS_Eval: do not detect module");
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsvalue_to_heap(JS_Eval(ctx, js_code, strlen(js_code), filename, evalFlags));
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnedHeapChar *QTS_Typeof(JSContext *ctx, JSValueConst *value) {
|
|
||||||
const char *result = "unknown";
|
|
||||||
uint32_t tag = JS_VALUE_GET_TAG(*value);
|
|
||||||
|
|
||||||
if (JS_IsNumber(*value)) {
|
|
||||||
result = "number";
|
|
||||||
} else if (JS_IsBigInt(ctx, *value)) {
|
|
||||||
result = "bigint";
|
|
||||||
} else if (JS_IsBigFloat(*value)) {
|
|
||||||
result = "bigfloat";
|
|
||||||
} else if (JS_IsBigDecimal(*value)) {
|
|
||||||
result = "bigdecimal";
|
|
||||||
} else if (JS_IsFunction(ctx, *value)) {
|
|
||||||
result = "function";
|
|
||||||
} else if (JS_IsBool(*value)) {
|
|
||||||
result = "boolean";
|
|
||||||
} else if (JS_IsNull(*value)) {
|
|
||||||
result = "object";
|
|
||||||
} else if (JS_IsUndefined(*value)) {
|
|
||||||
result = "undefined";
|
|
||||||
} else if (JS_IsUninitialized(*value)) {
|
|
||||||
result = "undefined";
|
|
||||||
} else if (JS_IsString(*value)) {
|
|
||||||
result = "string";
|
|
||||||
} else if (JS_IsSymbol(*value)) {
|
|
||||||
result = "symbol";
|
|
||||||
} else if (JS_IsObject(*value)) {
|
|
||||||
result = "object";
|
|
||||||
}
|
|
||||||
|
|
||||||
char *out = strdup(result);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_GetGlobalObject(JSContext *ctx) {
|
|
||||||
return jsvalue_to_heap(JS_GetGlobalObject(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue *QTS_NewPromiseCapability(JSContext *ctx, JSValue **resolve_funcs_out) {
|
|
||||||
JSValue resolve_funcs[2];
|
|
||||||
JSValue promise = JS_NewPromiseCapability(ctx, resolve_funcs);
|
|
||||||
resolve_funcs_out[0] = jsvalue_to_heap(resolve_funcs[0]);
|
|
||||||
resolve_funcs_out[1] = jsvalue_to_heap(resolve_funcs[1]);
|
|
||||||
return jsvalue_to_heap(promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_TestStringArg(const char *string) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_BuildIsDebug() {
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int QTS_BuildIsAsyncify() {
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Module loading helpers
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// C -> Host Callbacks
|
|
||||||
// Note: inside EM_JS, we need to use ['...'] subscript syntax for accessing JS
|
|
||||||
// objects, because in optimized builds, Closure compiler will mangle all the
|
|
||||||
// names.
|
|
||||||
|
|
||||||
// -------------------
|
|
||||||
// function: C -> Host
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
EM_JS(MaybeAsync(JSValue *), qts_host_call_function, (JSContext * ctx, JSValueConst *this_ptr, int argc, JSValueConst *argv, uint32_t magic_func_id), {
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
const asyncify = {['handleSleep'] : Asyncify.handleSleep};
|
|
||||||
#else
|
|
||||||
const asyncify = undefined;
|
|
||||||
#endif
|
|
||||||
return Module['callbacks']['callFunction'](asyncify, ctx, this_ptr, argc, argv, magic_func_id);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Function: QuickJS -> C
|
|
||||||
JSValue qts_call_function(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) {
|
|
||||||
JSValue *result_ptr = qts_host_call_function(ctx, &this_val, argc, argv, magic);
|
|
||||||
if (result_ptr == NULL) {
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
JSValue result = *result_ptr;
|
|
||||||
free(result_ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function: Host -> QuickJS
|
|
||||||
JSValue *QTS_NewFunction(JSContext *ctx, uint32_t func_id, const char *name) {
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
char msg[500];
|
|
||||||
sprintf(msg, "new_function(name: %s, magic: %d)", name, func_id);
|
|
||||||
QTS_DEBUG(msg)
|
|
||||||
#endif
|
|
||||||
JSValue func_obj = JS_NewCFunctionMagic(
|
|
||||||
/* context */ ctx,
|
|
||||||
/* JSCFunctionMagic* */ &qts_call_function,
|
|
||||||
/* name */ name,
|
|
||||||
/* min argc */ 0,
|
|
||||||
/* function type */ JS_CFUNC_generic_magic,
|
|
||||||
/* magic: fn id */ func_id);
|
|
||||||
return jsvalue_to_heap(func_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValueConst *QTS_ArgvGetJSValueConstPointer(JSValueConst *argv, int index) {
|
|
||||||
return &argv[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
// interrupt: C -> Host
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
EM_JS(int, qts_host_interrupt_handler, (JSRuntime * rt), {
|
|
||||||
// Async not supported here.
|
|
||||||
// #ifdef QTS_ASYNCIFY
|
|
||||||
// const asyncify = Asyncify;
|
|
||||||
// #else
|
|
||||||
const asyncify = undefined;
|
|
||||||
// #endif
|
|
||||||
return Module['callbacks']['shouldInterrupt'](asyncify, rt);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// interrupt: QuickJS -> C
|
|
||||||
int qts_interrupt_handler(JSRuntime *rt, void *_unused) {
|
|
||||||
return qts_host_interrupt_handler(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// interrupt: Host -> QuickJS
|
|
||||||
void QTS_RuntimeEnableInterruptHandler(JSRuntime *rt) {
|
|
||||||
JS_SetInterruptHandler(rt, &qts_interrupt_handler, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_RuntimeDisableInterruptHandler(JSRuntime *rt) {
|
|
||||||
JS_SetInterruptHandler(rt, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------
|
|
||||||
// load module: C -> Host
|
|
||||||
// TODO: a future version can support host returning JSModuleDef* directly;
|
|
||||||
// for now we only support loading module source code.
|
|
||||||
|
|
||||||
/*
|
|
||||||
The module loading model under ASYNCIFY is convoluted. We need to make sure we
|
|
||||||
never have an async request running concurrently for loading modules.
|
|
||||||
|
|
||||||
The first implemenation looked like this:
|
|
||||||
|
|
||||||
C HOST SUSPENDED
|
|
||||||
qts_host_load_module(name) ------> false
|
|
||||||
call rt.loadModule(name) false
|
|
||||||
Start async load module false
|
|
||||||
Suspend C true
|
|
||||||
Async load complete true
|
|
||||||
< --------------- QTS_CompileModule(source) true
|
|
||||||
QTS_Eval(source, COMPILE_ONLY) true
|
|
||||||
Loaded module has import true
|
|
||||||
qts_host_load_module(dep) -------> true
|
|
||||||
call rt.loadModule(dep) true
|
|
||||||
Start async load module true
|
|
||||||
ALREADY SUSPENDED, CRASH
|
|
||||||
|
|
||||||
We can solve this in two different ways:
|
|
||||||
|
|
||||||
1. Return to C as soon as we async load the module source.
|
|
||||||
That way, we unsuspend before calling QTS_CompileModule.
|
|
||||||
2. Once we load the module, use a new API to detect and async
|
|
||||||
load the module's downstream dependencies. This way
|
|
||||||
they're loaded synchronously so we don't need to suspend "again".
|
|
||||||
|
|
||||||
Probably we could optimize (2) to make it more performant, eg with parallel
|
|
||||||
loading, but (1) seems much easier to implement in the sort run.
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSModuleDef *qts_compile_module(JSContext *ctx, const char *module_name, BorrowedHeapChar *module_body) {
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
char msg[500];
|
|
||||||
sprintf(msg, "QTS_CompileModule(ctx: %p, name: %s, bodyLength: %lu)", ctx, module_name, strlen(module_body));
|
|
||||||
QTS_DEBUG(msg)
|
|
||||||
#endif
|
|
||||||
JSValue func_val = JS_Eval(ctx, module_body, strlen(module_body), module_name, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
|
||||||
if (JS_IsException(func_val)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// TODO: Is exception ok?
|
|
||||||
// TODO: set import.meta?
|
|
||||||
JSModuleDef *module = JS_VALUE_GET_PTR(func_val);
|
|
||||||
JS_FreeValue(ctx, func_val);
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
EM_JS(MaybeAsync(char *), qts_host_load_module_source, (JSRuntime * rt, JSContext *ctx, const char *module_name), {
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
const asyncify = {['handleSleep'] : Asyncify.handleSleep};
|
|
||||||
#else
|
|
||||||
const asyncify = undefined;
|
|
||||||
#endif
|
|
||||||
// https://emscripten.org/docs/api_reference/preamble.js.html#UTF8ToString
|
|
||||||
const moduleNameString = UTF8ToString(module_name);
|
|
||||||
return Module['callbacks']['loadModuleSource'](asyncify, rt, ctx, moduleNameString);
|
|
||||||
});
|
|
||||||
|
|
||||||
EM_JS(MaybeAsync(char *), qts_host_normalize_module, (JSRuntime * rt, JSContext *ctx, const char *module_base_name, const char *module_name), {
|
|
||||||
#ifdef QTS_ASYNCIFY
|
|
||||||
const asyncify = {['handleSleep'] : Asyncify.handleSleep};
|
|
||||||
#else
|
|
||||||
const asyncify = undefined;
|
|
||||||
#endif
|
|
||||||
// https://emscripten.org/docs/api_reference/preamble.js.html#UTF8ToString
|
|
||||||
const moduleBaseNameString = UTF8ToString(module_base_name);
|
|
||||||
const moduleNameString = UTF8ToString(module_name);
|
|
||||||
return Module['callbacks']['normalizeModule'](asyncify, rt, ctx, moduleBaseNameString, moduleNameString);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// load module: QuickJS -> C
|
|
||||||
// See js_module_loader in quickjs/quickjs-libc.c:567
|
|
||||||
JSModuleDef *qts_load_module(JSContext *ctx, const char *module_name, void *_unused) {
|
|
||||||
JSRuntime *rt = JS_GetRuntime(ctx);
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
char msg[500];
|
|
||||||
sprintf(msg, "qts_load_module(rt: %p, ctx: %p, name: %s)", rt, ctx, module_name);
|
|
||||||
QTS_DEBUG(msg)
|
|
||||||
#endif
|
|
||||||
char *module_source = qts_host_load_module_source(rt, ctx, module_name);
|
|
||||||
if (module_source == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSModuleDef *module = qts_compile_module(ctx, module_name, module_source);
|
|
||||||
free(module_source);
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *qts_normalize_module(JSContext *ctx, const char *module_base_name, const char *module_name, void *_unused) {
|
|
||||||
JSRuntime *rt = JS_GetRuntime(ctx);
|
|
||||||
#ifdef QTS_DEBUG_MODE
|
|
||||||
char msg[500];
|
|
||||||
sprintf(msg, "qts_normalize_module(rt: %p, ctx: %p, base_name: %s, name: %s)", rt, ctx, module_base_name, module_name);
|
|
||||||
QTS_DEBUG(msg)
|
|
||||||
#endif
|
|
||||||
char *em_module_name = qts_host_normalize_module(rt, ctx, module_base_name, module_name);
|
|
||||||
char *js_module_name = js_strdup(ctx, em_module_name);
|
|
||||||
free(em_module_name);
|
|
||||||
return js_module_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load module: Host -> QuickJS
|
|
||||||
void QTS_RuntimeEnableModuleLoader(JSRuntime *rt, int use_custom_normalize) {
|
|
||||||
JSModuleNormalizeFunc *module_normalize = NULL; /* use default name normalizer */
|
|
||||||
if (use_custom_normalize) {
|
|
||||||
module_normalize = &qts_normalize_module;
|
|
||||||
}
|
|
||||||
JS_SetModuleLoaderFunc(rt, module_normalize, &qts_load_module, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QTS_RuntimeDisableModuleLoader(JSRuntime *rt) {
|
|
||||||
JS_SetModuleLoaderFunc(rt, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
declare function awaitYield<T>(value: T | Promise<T>): Generator<T | Promise<T>, T, T>;
|
|
||||||
declare function awaitYieldOf<T, Yielded>(generator: Generator<Yielded | Promise<Yielded>, T, Yielded>): Generator<T | Promise<T>, T, T>;
|
|
||||||
export type AwaitYield = typeof awaitYield & {
|
|
||||||
of: typeof awaitYieldOf;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Create a function that may or may not be async, using a generator
|
|
||||||
*
|
|
||||||
* Within the generator, call `yield* awaited(maybePromise)` to await a value
|
|
||||||
* that may or may not be a promise.
|
|
||||||
*
|
|
||||||
* If the inner function never yields a promise, it will return synchronously.
|
|
||||||
*/
|
|
||||||
export declare function maybeAsyncFn<
|
|
||||||
/** Function arguments */
|
|
||||||
Args extends any[], This,
|
|
||||||
/** Function return type */
|
|
||||||
Return,
|
|
||||||
/** Yields to unwrap */
|
|
||||||
Yielded>(that: This, fn: (this: This, awaited: AwaitYield, ...args: Args) => Generator<Yielded | Promise<Yielded>, Return, Yielded>): (...args: Args) => Return | Promise<Return>;
|
|
||||||
export type MaybeAsyncBlock<Return, This, Yielded, Args extends any[] = []> = (this: This, awaited: AwaitYield, ...args: Args) => Generator<Yielded | Promise<Yielded>, Return, Yielded>;
|
|
||||||
export declare function maybeAsync<Return, This, Yielded>(that: This, startGenerator: (this: This, await: AwaitYield) => Generator<Yielded | Promise<Yielded>, Return, Yielded>): Return | Promise<Return>;
|
|
||||||
export declare function awaitEachYieldedPromise<Yielded, Returned>(gen: Generator<Yielded | Promise<Yielded>, Returned, Yielded>): Returned | Promise<Returned>;
|
|
||||||
export {};
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.awaitEachYieldedPromise = exports.maybeAsync = exports.maybeAsyncFn = void 0;
|
|
||||||
function* awaitYield(value) {
|
|
||||||
return (yield value);
|
|
||||||
}
|
|
||||||
function awaitYieldOf(generator) {
|
|
||||||
return awaitYield(awaitEachYieldedPromise(generator));
|
|
||||||
}
|
|
||||||
const AwaitYield = awaitYield;
|
|
||||||
AwaitYield.of = awaitYieldOf;
|
|
||||||
/**
|
|
||||||
* Create a function that may or may not be async, using a generator
|
|
||||||
*
|
|
||||||
* Within the generator, call `yield* awaited(maybePromise)` to await a value
|
|
||||||
* that may or may not be a promise.
|
|
||||||
*
|
|
||||||
* If the inner function never yields a promise, it will return synchronously.
|
|
||||||
*/
|
|
||||||
function maybeAsyncFn(that, fn) {
|
|
||||||
return (...args) => {
|
|
||||||
const generator = fn.call(that, AwaitYield, ...args);
|
|
||||||
return awaitEachYieldedPromise(generator);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.maybeAsyncFn = maybeAsyncFn;
|
|
||||||
class Example {
|
|
||||||
constructor() {
|
|
||||||
this.maybeAsyncMethod = maybeAsyncFn(this, function* (awaited, a) {
|
|
||||||
yield* awaited(new Promise((resolve) => setTimeout(resolve, a)));
|
|
||||||
return 5;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function maybeAsync(that, startGenerator) {
|
|
||||||
const generator = startGenerator.call(that, AwaitYield);
|
|
||||||
return awaitEachYieldedPromise(generator);
|
|
||||||
}
|
|
||||||
exports.maybeAsync = maybeAsync;
|
|
||||||
function awaitEachYieldedPromise(gen) {
|
|
||||||
function handleNextStep(step) {
|
|
||||||
if (step.done) {
|
|
||||||
return step.value;
|
|
||||||
}
|
|
||||||
if (step.value instanceof Promise) {
|
|
||||||
return step.value.then((value) => handleNextStep(gen.next(value)), (error) => handleNextStep(gen.throw(error)));
|
|
||||||
}
|
|
||||||
return handleNextStep(gen.next(step.value));
|
|
||||||
}
|
|
||||||
return handleNextStep(gen.next());
|
|
||||||
}
|
|
||||||
exports.awaitEachYieldedPromise = awaitEachYieldedPromise;
|
|
||||||
//# sourceMappingURL=asyncify-helpers.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"asyncify-helpers.js","sourceRoot":"","sources":["../ts/asyncify-helpers.ts"],"names":[],"mappings":";;;AAAA,QAAQ,CAAC,CAAC,UAAU,CAAI,KAAqB;IAC3C,OAAO,CAAC,MAAM,KAAK,CAAM,CAAA;AAC3B,CAAC;AAED,SAAS,YAAY,CACnB,SAA4D;IAE5D,OAAO,UAAU,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAA;AACvD,CAAC;AAMD,MAAM,UAAU,GAAe,UAAwB,CAAA;AACvD,UAAU,CAAC,EAAE,GAAG,YAAY,CAAA;AAE5B;;;;;;;GAOG;AACH,SAAgB,YAAY,CAS1B,IAAU,EACV,EAI2D;IAE3D,OAAO,CAAC,GAAG,IAAU,EAAE,EAAE;QACvB,MAAM,SAAS,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAA;QACpD,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAA;IAC3C,CAAC,CAAA;AACH,CAAC;AApBD,oCAoBC;AAED,MAAM,OAAO;IAAb;QACU,qBAAgB,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAS;YACzE,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;YAChE,OAAO,CAAC,CAAA;QACV,CAAC,CAAC,CAAA;IACJ,CAAC;CAAA;AAQD,SAAgB,UAAU,CACxB,IAAU,EACV,cAG2D;IAE3D,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACvD,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAA;AAC3C,CAAC;AATD,gCASC;AAED,SAAgB,uBAAuB,CACrC,GAA6D;IAI7D,SAAS,cAAc,CAAC,IAAgB;QACtC,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,OAAO,IAAI,CAAC,KAAK,CAAA;SAClB;QAED,IAAI,IAAI,CAAC,KAAK,YAAY,OAAO,EAAE;YACjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CACpB,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAC1C,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAC5C,CAAA;SACF;QAED,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IAC7C,CAAC;IAED,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;AACnC,CAAC;AArBD,0DAqBC","sourcesContent":["function* awaitYield<T>(value: T | Promise<T>) {\n return (yield value) as T\n}\n\nfunction awaitYieldOf<T, Yielded>(\n generator: Generator<Yielded | Promise<Yielded>, T, Yielded>\n): Generator<T | Promise<T>, T, T> {\n return awaitYield(awaitEachYieldedPromise(generator))\n}\n\nexport type AwaitYield = typeof awaitYield & {\n of: typeof awaitYieldOf\n}\n\nconst AwaitYield: AwaitYield = awaitYield as AwaitYield\nAwaitYield.of = awaitYieldOf\n\n/**\n * Create a function that may or may not be async, using a generator\n *\n * Within the generator, call `yield* awaited(maybePromise)` to await a value\n * that may or may not be a promise.\n *\n * If the inner function never yields a promise, it will return synchronously.\n */\nexport function maybeAsyncFn<\n /** Function arguments */\n Args extends any[],\n This,\n /** Function return type */\n Return,\n /** Yields to unwrap */\n Yielded\n>(\n that: This,\n fn: (\n this: This,\n awaited: AwaitYield,\n ...args: Args\n ) => Generator<Yielded | Promise<Yielded>, Return, Yielded>\n): (...args: Args) => Return | Promise<Return> {\n return (...args: Args) => {\n const generator = fn.call(that, AwaitYield, ...args)\n return awaitEachYieldedPromise(generator)\n }\n}\n\nclass Example {\n private maybeAsyncMethod = maybeAsyncFn(this, function* (awaited, a: number) {\n yield* awaited(new Promise((resolve) => setTimeout(resolve, a)))\n return 5\n })\n}\n\nexport type MaybeAsyncBlock<Return, This, Yielded, Args extends any[] = []> = (\n this: This,\n awaited: AwaitYield,\n ...args: Args\n) => Generator<Yielded | Promise<Yielded>, Return, Yielded>\n\nexport function maybeAsync<Return, This, Yielded>(\n that: This,\n startGenerator: (\n this: This,\n await: AwaitYield\n ) => Generator<Yielded | Promise<Yielded>, Return, Yielded>\n): Return | Promise<Return> {\n const generator = startGenerator.call(that, AwaitYield)\n return awaitEachYieldedPromise(generator)\n}\n\nexport function awaitEachYieldedPromise<Yielded, Returned>(\n gen: Generator<Yielded | Promise<Yielded>, Returned, Yielded>\n): Returned | Promise<Returned> {\n type NextResult = ReturnType<typeof gen.next>\n\n function handleNextStep(step: NextResult): Returned | Promise<Returned> {\n if (step.done) {\n return step.value\n }\n\n if (step.value instanceof Promise) {\n return step.value.then(\n (value) => handleNextStep(gen.next(value)),\n (error) => handleNextStep(gen.throw(error))\n )\n }\n\n return handleNextStep(gen.next(step.value))\n }\n\n return handleNextStep(gen.next())\n}\n"]}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import { QuickJSContext } from "./context";
|
|
||||||
import { QuickJSAsyncEmscriptenModule } from "./emscripten-types";
|
|
||||||
import { QuickJSAsyncFFI } from "./variants";
|
|
||||||
import { JSRuntimePointer } from "./types-ffi";
|
|
||||||
import { Lifetime } from "./lifetime";
|
|
||||||
import { QuickJSModuleCallbacks } from "./module";
|
|
||||||
import { QuickJSAsyncRuntime } from "./runtime-asyncify";
|
|
||||||
import { ContextEvalOptions, QuickJSHandle } from "./types";
|
|
||||||
import { VmCallResult } from "./vm-interface";
|
|
||||||
export type AsyncFunctionImplementation = (this: QuickJSHandle, ...args: QuickJSHandle[]) => Promise<QuickJSHandle | VmCallResult<QuickJSHandle> | void>;
|
|
||||||
/**
|
|
||||||
* Asyncified version of [[QuickJSContext]].
|
|
||||||
*
|
|
||||||
* *Asyncify* allows normally synchronous code to wait for asynchronous Promises
|
|
||||||
* or callbacks. The asyncified version of QuickJSContext can wait for async
|
|
||||||
* host functions as though they were synchronous.
|
|
||||||
*/
|
|
||||||
export declare class QuickJSAsyncContext extends QuickJSContext {
|
|
||||||
runtime: QuickJSAsyncRuntime;
|
|
||||||
/** @private */
|
|
||||||
protected module: QuickJSAsyncEmscriptenModule;
|
|
||||||
/** @private */
|
|
||||||
protected ffi: QuickJSAsyncFFI;
|
|
||||||
/** @private */
|
|
||||||
protected rt: Lifetime<JSRuntimePointer>;
|
|
||||||
/** @private */
|
|
||||||
protected callbacks: QuickJSModuleCallbacks;
|
|
||||||
/**
|
|
||||||
* Asyncified version of [[evalCode]].
|
|
||||||
*/
|
|
||||||
evalCodeAsync(code: string, filename?: string,
|
|
||||||
/** See [[EvalFlags]] for number semantics */
|
|
||||||
options?: number | ContextEvalOptions): Promise<VmCallResult<QuickJSHandle>>;
|
|
||||||
/**
|
|
||||||
* Similar to [[newFunction]].
|
|
||||||
* Convert an async host Javascript function into a synchronous QuickJS function value.
|
|
||||||
*
|
|
||||||
* Whenever QuickJS calls this function, the VM's stack will be unwound while
|
|
||||||
* waiting the async function to complete, and then restored when the returned
|
|
||||||
* promise resolves.
|
|
||||||
*
|
|
||||||
* Asyncified functions must never call other asyncified functions or
|
|
||||||
* `import`, even indirectly, because the stack cannot be unwound twice.
|
|
||||||
*
|
|
||||||
* See [Emscripten's docs on Asyncify](https://emscripten.org/docs/porting/asyncify.html).
|
|
||||||
*/
|
|
||||||
newAsyncifiedFunction(name: string, fn: AsyncFunctionImplementation): QuickJSHandle;
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.QuickJSAsyncContext = void 0;
|
|
||||||
const context_1 = require("./context");
|
|
||||||
const debug_1 = require("./debug");
|
|
||||||
const types_1 = require("./types");
|
|
||||||
/**
|
|
||||||
* Asyncified version of [[QuickJSContext]].
|
|
||||||
*
|
|
||||||
* *Asyncify* allows normally synchronous code to wait for asynchronous Promises
|
|
||||||
* or callbacks. The asyncified version of QuickJSContext can wait for async
|
|
||||||
* host functions as though they were synchronous.
|
|
||||||
*/
|
|
||||||
class QuickJSAsyncContext extends context_1.QuickJSContext {
|
|
||||||
/**
|
|
||||||
* Asyncified version of [[evalCode]].
|
|
||||||
*/
|
|
||||||
async evalCodeAsync(code, filename = "eval.js",
|
|
||||||
/** See [[EvalFlags]] for number semantics */
|
|
||||||
options) {
|
|
||||||
const detectModule = (options === undefined ? 1 : 0);
|
|
||||||
const flags = (0, types_1.evalOptionsToFlags)(options);
|
|
||||||
let resultPtr = 0;
|
|
||||||
try {
|
|
||||||
resultPtr = await this.memory
|
|
||||||
.newHeapCharPointer(code)
|
|
||||||
.consume((charHandle) => this.ffi.QTS_Eval_MaybeAsync(this.ctx.value, charHandle.value, filename, detectModule, flags));
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
(0, debug_1.debugLog)("QTS_Eval_MaybeAsync threw", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
const errorPtr = this.ffi.QTS_ResolveException(this.ctx.value, resultPtr);
|
|
||||||
if (errorPtr) {
|
|
||||||
this.ffi.QTS_FreeValuePointer(this.ctx.value, resultPtr);
|
|
||||||
return { error: this.memory.heapValueHandle(errorPtr) };
|
|
||||||
}
|
|
||||||
return { value: this.memory.heapValueHandle(resultPtr) };
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Similar to [[newFunction]].
|
|
||||||
* Convert an async host Javascript function into a synchronous QuickJS function value.
|
|
||||||
*
|
|
||||||
* Whenever QuickJS calls this function, the VM's stack will be unwound while
|
|
||||||
* waiting the async function to complete, and then restored when the returned
|
|
||||||
* promise resolves.
|
|
||||||
*
|
|
||||||
* Asyncified functions must never call other asyncified functions or
|
|
||||||
* `import`, even indirectly, because the stack cannot be unwound twice.
|
|
||||||
*
|
|
||||||
* See [Emscripten's docs on Asyncify](https://emscripten.org/docs/porting/asyncify.html).
|
|
||||||
*/
|
|
||||||
newAsyncifiedFunction(name, fn) {
|
|
||||||
return this.newFunction(name, fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSAsyncContext = QuickJSAsyncContext;
|
|
||||||
//# sourceMappingURL=context-asyncify.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"context-asyncify.js","sourceRoot":"","sources":["../ts/context-asyncify.ts"],"names":[],"mappings":";;;AAAA,uCAA0C;AAC1C,mCAAkC;AAOlC,mCAA+E;AAQ/E;;;;;;GAMG;AACH,MAAa,mBAAoB,SAAQ,wBAAc;IAWrD;;OAEG;IACH,KAAK,CAAC,aAAa,CACjB,IAAY,EACZ,WAAmB,SAAS;IAC5B,6CAA6C;IAC7C,OAAqC;QAErC,MAAM,YAAY,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAqB,CAAA;QACxE,MAAM,KAAK,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAc,CAAA;QACtD,IAAI,SAAS,GAAG,CAAmB,CAAA;QACnC,IAAI;YACF,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM;iBAC1B,kBAAkB,CAAC,IAAI,CAAC;iBACxB,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CACtB,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAC1B,IAAI,CAAC,GAAG,CAAC,KAAK,EACd,UAAU,CAAC,KAAK,EAChB,QAAQ,EACR,YAAY,EACZ,KAAK,CACN,CACF,CAAA;SACJ;QAAC,OAAO,KAAK,EAAE;YACd,IAAA,gBAAQ,EAAC,2BAA2B,EAAE,KAAK,CAAC,CAAA;YAC5C,MAAM,KAAK,CAAA;SACZ;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QACzE,IAAI,QAAQ,EAAE;YACZ,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YACxD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAA;SACxD;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAA;IAC1D,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,qBAAqB,CAAC,IAAY,EAAE,EAA+B;QACjE,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAS,CAAC,CAAA;IAC1C,CAAC;CACF;AA/DD,kDA+DC","sourcesContent":["import { QuickJSContext } from \"./context\"\nimport { debugLog } from \"./debug\"\nimport { QuickJSAsyncEmscriptenModule } from \"./emscripten-types\"\nimport { QuickJSAsyncFFI } from \"./variants\"\nimport { EvalDetectModule, EvalFlags, JSRuntimePointer, JSValuePointer } from \"./types-ffi\"\nimport { Lifetime } from \"./lifetime\"\nimport { QuickJSModuleCallbacks } from \"./module\"\nimport { QuickJSAsyncRuntime } from \"./runtime-asyncify\"\nimport { ContextEvalOptions, evalOptionsToFlags, QuickJSHandle } from \"./types\"\nimport { VmCallResult } from \"./vm-interface\"\n\nexport type AsyncFunctionImplementation = (\n this: QuickJSHandle,\n ...args: QuickJSHandle[]\n) => Promise<QuickJSHandle | VmCallResult<QuickJSHandle> | void>\n\n/**\n * Asyncified version of [[QuickJSContext]].\n *\n * *Asyncify* allows normally synchronous code to wait for asynchronous Promises\n * or callbacks. The asyncified version of QuickJSContext can wait for async\n * host functions as though they were synchronous.\n */\nexport class QuickJSAsyncContext extends QuickJSContext {\n public declare runtime: QuickJSAsyncRuntime\n /** @private */\n protected declare module: QuickJSAsyncEmscriptenModule\n /** @private */\n protected declare ffi: QuickJSAsyncFFI\n /** @private */\n protected declare rt: Lifetime<JSRuntimePointer>\n /** @private */\n protected declare callbacks: QuickJSModuleCallbacks\n\n /**\n * Asyncified version of [[evalCode]].\n */\n async evalCodeAsync(\n code: string,\n filename: string = \"eval.js\",\n /** See [[EvalFlags]] for number semantics */\n options?: number | ContextEvalOptions\n ): Promise<VmCallResult<QuickJSHandle>> {\n const detectModule = (options === undefined ? 1 : 0) as EvalDetectModule\n const flags = evalOptionsToFlags(options) as EvalFlags\n let resultPtr = 0 as JSValuePointer\n try {\n resultPtr = await this.memory\n .newHeapCharPointer(code)\n .consume((charHandle) =>\n this.ffi.QTS_Eval_MaybeAsync(\n this.ctx.value,\n charHandle.value,\n filename,\n detectModule,\n flags\n )\n )\n } catch (error) {\n debugLog(\"QTS_Eval_MaybeAsync threw\", error)\n throw error\n }\n const errorPtr = this.ffi.QTS_ResolveException(this.ctx.value, resultPtr)\n if (errorPtr) {\n this.ffi.QTS_FreeValuePointer(this.ctx.value, resultPtr)\n return { error: this.memory.heapValueHandle(errorPtr) }\n }\n return { value: this.memory.heapValueHandle(resultPtr) }\n }\n\n /**\n * Similar to [[newFunction]].\n * Convert an async host Javascript function into a synchronous QuickJS function value.\n *\n * Whenever QuickJS calls this function, the VM's stack will be unwound while\n * waiting the async function to complete, and then restored when the returned\n * promise resolves.\n *\n * Asyncified functions must never call other asyncified functions or\n * `import`, even indirectly, because the stack cannot be unwound twice.\n *\n * See [Emscripten's docs on Asyncify](https://emscripten.org/docs/porting/asyncify.html).\n */\n newAsyncifiedFunction(name: string, fn: AsyncFunctionImplementation): QuickJSHandle {\n return this.newFunction(name, fn as any)\n }\n}\n"]}
|
|
||||||
371
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/context.d.ts
generated
vendored
371
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/context.d.ts
generated
vendored
@@ -1,371 +0,0 @@
|
|||||||
import { QuickJSDeferredPromise } from "./deferred-promise";
|
|
||||||
import type { EitherModule } from "./emscripten-types";
|
|
||||||
import { JSBorrowedCharPointer, JSContextPointer, JSRuntimePointer, JSValueConstPointer, JSValuePointer } from "./types-ffi";
|
|
||||||
import { Disposable, Lifetime, Scope } from "./lifetime";
|
|
||||||
import { ModuleMemory } from "./memory";
|
|
||||||
import { QuickJSModuleCallbacks } from "./module";
|
|
||||||
import { QuickJSRuntime } from "./runtime";
|
|
||||||
import { ContextEvalOptions, EitherFFI, JSValue, PromiseExecutor, QuickJSHandle } from "./types";
|
|
||||||
import { LowLevelJavascriptVm, SuccessOrFail, VmCallResult, VmFunctionImplementation, VmPropertyDescriptor } from "./vm-interface";
|
|
||||||
/**
|
|
||||||
* Property key for getting or setting a property on a handle with
|
|
||||||
* [[QuickJSContext.getProp]], [[QuickJSContext.setProp]], or [[QuickJSContext.defineProp]].
|
|
||||||
*/
|
|
||||||
export type QuickJSPropertyKey = number | string | QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
declare class ContextMemory extends ModuleMemory implements Disposable {
|
|
||||||
readonly owner: QuickJSRuntime;
|
|
||||||
readonly ctx: Lifetime<JSContextPointer>;
|
|
||||||
readonly rt: Lifetime<JSRuntimePointer>;
|
|
||||||
readonly module: EitherModule;
|
|
||||||
readonly ffi: EitherFFI;
|
|
||||||
readonly scope: Scope;
|
|
||||||
/** @private */
|
|
||||||
constructor(args: {
|
|
||||||
owner: QuickJSRuntime;
|
|
||||||
module: EitherModule;
|
|
||||||
ffi: EitherFFI;
|
|
||||||
ctx: Lifetime<JSContextPointer>;
|
|
||||||
rt: Lifetime<JSRuntimePointer>;
|
|
||||||
ownedLifetimes?: Disposable[];
|
|
||||||
});
|
|
||||||
get alive(): boolean;
|
|
||||||
dispose(): void;
|
|
||||||
/**
|
|
||||||
* Track `lifetime` so that it is disposed when this scope is disposed.
|
|
||||||
*/
|
|
||||||
manage<T extends Disposable>(lifetime: T): T;
|
|
||||||
copyJSValue: (ptr: JSValuePointer | JSValueConstPointer) => any;
|
|
||||||
freeJSValue: (ptr: JSValuePointer) => void;
|
|
||||||
consumeJSCharPointer(ptr: JSBorrowedCharPointer): string;
|
|
||||||
heapValueHandle(ptr: JSValuePointer): JSValue;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* QuickJSContext wraps a QuickJS Javascript context (JSContext*) within a
|
|
||||||
* runtime. The contexts within the same runtime may exchange objects freely.
|
|
||||||
* You can think of separate runtimes like different domains in a browser, and
|
|
||||||
* the contexts within a runtime like the different windows open to the same
|
|
||||||
* domain. The {@link runtime} references the context's runtime.
|
|
||||||
*
|
|
||||||
* This class's methods return {@link QuickJSHandle}, which wrap C pointers (JSValue*).
|
|
||||||
* It's the caller's responsibility to call `.dispose()` on any
|
|
||||||
* handles you create to free memory once you're done with the handle.
|
|
||||||
*
|
|
||||||
* Use {@link QuickJSRuntime.newContext} or {@link QuickJSWASMModule.newContext}
|
|
||||||
* to create a new QuickJSContext.
|
|
||||||
*
|
|
||||||
* Create QuickJS values inside the interpreter with methods like
|
|
||||||
* [[newNumber]], [[newString]], [[newArray]], [[newObject]],
|
|
||||||
* [[newFunction]], and [[newPromise]].
|
|
||||||
*
|
|
||||||
* Call [[setProp]] or [[defineProp]] to customize objects. Use those methods
|
|
||||||
* with [[global]] to expose the values you create to the interior of the
|
|
||||||
* interpreter, so they can be used in [[evalCode]].
|
|
||||||
*
|
|
||||||
* Use [[evalCode]] or [[callFunction]] to execute Javascript inside the VM. If
|
|
||||||
* you're using asynchronous code inside the QuickJSContext, you may need to also
|
|
||||||
* call [[executePendingJobs]]. Executing code inside the runtime returns a
|
|
||||||
* result object representing successful execution or an error. You must dispose
|
|
||||||
* of any such results to avoid leaking memory inside the VM.
|
|
||||||
*
|
|
||||||
* Implement memory and CPU constraints at the runtime level, using [[runtime]].
|
|
||||||
* See {@link QuickJSRuntime} for more information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
export declare class QuickJSContext implements LowLevelJavascriptVm<QuickJSHandle>, Disposable {
|
|
||||||
/**
|
|
||||||
* The runtime that created this context.
|
|
||||||
*/
|
|
||||||
readonly runtime: QuickJSRuntime;
|
|
||||||
/** @private */
|
|
||||||
protected readonly ctx: Lifetime<JSContextPointer>;
|
|
||||||
/** @private */
|
|
||||||
protected readonly rt: Lifetime<JSRuntimePointer>;
|
|
||||||
/** @private */
|
|
||||||
protected readonly module: EitherModule;
|
|
||||||
/** @private */
|
|
||||||
protected readonly ffi: EitherFFI;
|
|
||||||
/** @private */
|
|
||||||
protected memory: ContextMemory;
|
|
||||||
/** @private */
|
|
||||||
protected _undefined: QuickJSHandle | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected _null: QuickJSHandle | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected _false: QuickJSHandle | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected _true: QuickJSHandle | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected _global: QuickJSHandle | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected _BigInt: QuickJSHandle | undefined;
|
|
||||||
/**
|
|
||||||
* Use {@link QuickJS.createVm} to create a QuickJSContext instance.
|
|
||||||
*/
|
|
||||||
constructor(args: {
|
|
||||||
module: EitherModule;
|
|
||||||
ffi: EitherFFI;
|
|
||||||
ctx: Lifetime<JSContextPointer>;
|
|
||||||
rt: Lifetime<JSRuntimePointer>;
|
|
||||||
runtime: QuickJSRuntime;
|
|
||||||
ownedLifetimes?: Disposable[];
|
|
||||||
callbacks: QuickJSModuleCallbacks;
|
|
||||||
});
|
|
||||||
get alive(): boolean;
|
|
||||||
/**
|
|
||||||
* Dispose of this VM's underlying resources.
|
|
||||||
*
|
|
||||||
* @throws Calling this method without disposing of all created handles
|
|
||||||
* will result in an error.
|
|
||||||
*/
|
|
||||||
dispose(): void;
|
|
||||||
/**
|
|
||||||
* [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined).
|
|
||||||
*/
|
|
||||||
get undefined(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null).
|
|
||||||
*/
|
|
||||||
get null(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* [`true`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/true).
|
|
||||||
*/
|
|
||||||
get true(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* [`false`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/false).
|
|
||||||
*/
|
|
||||||
get false(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* [`global`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects).
|
|
||||||
* A handle to the global object inside the interpreter.
|
|
||||||
* You can set properties to create global variables.
|
|
||||||
*/
|
|
||||||
get global(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Converts a Javascript number into a QuickJS value.
|
|
||||||
*/
|
|
||||||
newNumber(num: number): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) value.
|
|
||||||
*/
|
|
||||||
newString(str: string): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) value.
|
|
||||||
* No two symbols created with this function will be the same value.
|
|
||||||
*/
|
|
||||||
newUniqueSymbol(description: string | symbol): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Get a symbol from the [global registry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#shared_symbols_in_the_global_symbol_registry) for the given key.
|
|
||||||
* All symbols created with the same key will be the same value.
|
|
||||||
*/
|
|
||||||
newSymbolFor(key: string | symbol): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) value.
|
|
||||||
*/
|
|
||||||
newBigInt(num: bigint): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* `{}`.
|
|
||||||
* Create a new QuickJS [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer).
|
|
||||||
*
|
|
||||||
* @param prototype - Like [`Object.create`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create).
|
|
||||||
*/
|
|
||||||
newObject(prototype?: QuickJSHandle): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* `[]`.
|
|
||||||
* Create a new QuickJS [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
|
|
||||||
*/
|
|
||||||
newArray(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSDeferredPromise]]. Use `deferred.resolve(handle)` and
|
|
||||||
* `deferred.reject(handle)` to fulfill the promise handle available at `deferred.handle`.
|
|
||||||
* Note that you are responsible for calling `deferred.dispose()` to free the underlying
|
|
||||||
* resources; see the documentation on [[QuickJSDeferredPromise]] for details.
|
|
||||||
*/
|
|
||||||
newPromise(): QuickJSDeferredPromise;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSDeferredPromise]] that resolves when the
|
|
||||||
* given native Promise<QuickJSHandle> resolves. Rejections will be coerced
|
|
||||||
* to a QuickJS error.
|
|
||||||
*
|
|
||||||
* You can still resolve/reject the created promise "early" using its methods.
|
|
||||||
*/
|
|
||||||
newPromise(promise: Promise<QuickJSHandle>): QuickJSDeferredPromise;
|
|
||||||
/**
|
|
||||||
* Construct a new native Promise<QuickJSHandle>, and then convert it into a
|
|
||||||
* [[QuickJSDeferredPromise]].
|
|
||||||
*
|
|
||||||
* You can still resolve/reject the created promise "early" using its methods.
|
|
||||||
*/
|
|
||||||
newPromise(newPromiseFn: PromiseExecutor<QuickJSHandle, Error | QuickJSHandle>): QuickJSDeferredPromise;
|
|
||||||
/**
|
|
||||||
* Convert a Javascript function into a QuickJS function value.
|
|
||||||
* See [[VmFunctionImplementation]] for more details.
|
|
||||||
*
|
|
||||||
* A [[VmFunctionImplementation]] should not free its arguments or its return
|
|
||||||
* value. A VmFunctionImplementation should also not retain any references to
|
|
||||||
* its return value.
|
|
||||||
*
|
|
||||||
* To implement an async function, create a promise with [[newPromise]], then
|
|
||||||
* return the deferred promise handle from `deferred.handle` from your
|
|
||||||
* function implementation:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* const deferred = vm.newPromise()
|
|
||||||
* someNativeAsyncFunction().then(deferred.resolve)
|
|
||||||
* return deferred.handle
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
newFunction(name: string, fn: VmFunctionImplementation<QuickJSHandle>): QuickJSHandle;
|
|
||||||
newError(error: {
|
|
||||||
name: string;
|
|
||||||
message: string;
|
|
||||||
}): QuickJSHandle;
|
|
||||||
newError(message: string): QuickJSHandle;
|
|
||||||
newError(): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* `typeof` operator. **Not** [standards compliant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof).
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* Does not support BigInt values correctly.
|
|
||||||
*/
|
|
||||||
typeof(handle: QuickJSHandle): string;
|
|
||||||
/**
|
|
||||||
* Converts `handle` into a Javascript number.
|
|
||||||
* @returns `NaN` on error, otherwise a `number`.
|
|
||||||
*/
|
|
||||||
getNumber(handle: QuickJSHandle): number;
|
|
||||||
/**
|
|
||||||
* Converts `handle` to a Javascript string.
|
|
||||||
*/
|
|
||||||
getString(handle: QuickJSHandle): string;
|
|
||||||
/**
|
|
||||||
* Converts `handle` into a Javascript symbol. If the symbol is in the global
|
|
||||||
* registry in the guest, it will be created with Symbol.for on the host.
|
|
||||||
*/
|
|
||||||
getSymbol(handle: QuickJSHandle): symbol;
|
|
||||||
/**
|
|
||||||
* Converts `handle` to a Javascript bigint.
|
|
||||||
*/
|
|
||||||
getBigInt(handle: QuickJSHandle): bigint;
|
|
||||||
/**
|
|
||||||
* `Promise.resolve(value)`.
|
|
||||||
* Convert a handle containing a Promise-like value inside the VM into an
|
|
||||||
* actual promise on the host.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* You may need to call [[executePendingJobs]] to ensure that the promise is resolved.
|
|
||||||
*
|
|
||||||
* @param promiseLikeHandle - A handle to a Promise-like value with a `.then(onSuccess, onError)` method.
|
|
||||||
*/
|
|
||||||
resolvePromise(promiseLikeHandle: QuickJSHandle): Promise<VmCallResult<QuickJSHandle>>;
|
|
||||||
/**
|
|
||||||
* `handle[key]`.
|
|
||||||
* Get a property from a JSValue.
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string (which will be converted automatically).
|
|
||||||
*/
|
|
||||||
getProp(handle: QuickJSHandle, key: QuickJSPropertyKey): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* `handle[key] = value`.
|
|
||||||
* Set a property on a JSValue.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* Note that the QuickJS authors recommend using [[defineProp]] to define new
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string or number (which will be converted automatically to a JSValue).
|
|
||||||
*/
|
|
||||||
setProp(handle: QuickJSHandle, key: QuickJSPropertyKey, value: QuickJSHandle): void;
|
|
||||||
/**
|
|
||||||
* [`Object.defineProperty(handle, key, descriptor)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string or number (which will be converted automatically to a JSValue).
|
|
||||||
*/
|
|
||||||
defineProp(handle: QuickJSHandle, key: QuickJSPropertyKey, descriptor: VmPropertyDescriptor<QuickJSHandle>): void;
|
|
||||||
/**
|
|
||||||
* [`func.call(thisVal, ...args)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call).
|
|
||||||
* Call a JSValue as a function.
|
|
||||||
*
|
|
||||||
* See [[unwrapResult]], which will throw if the function returned an error, or
|
|
||||||
* return the result handle directly. If evaluation returned a handle containing
|
|
||||||
* a promise, use [[resolvePromise]] to convert it to a native promise and
|
|
||||||
* [[executePendingJobs]] to finish evaluating the promise.
|
|
||||||
*
|
|
||||||
* @returns A result. If the function threw synchronously, `result.error` be a
|
|
||||||
* handle to the exception. Otherwise `result.value` will be a handle to the
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
callFunction(func: QuickJSHandle, thisVal: QuickJSHandle, ...args: QuickJSHandle[]): VmCallResult<QuickJSHandle>;
|
|
||||||
/**
|
|
||||||
* Like [`eval(code)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Description).
|
|
||||||
* Evaluates the Javascript source `code` in the global scope of this VM.
|
|
||||||
* When working with async code, you many need to call [[executePendingJobs]]
|
|
||||||
* to execute callbacks pending after synchronous evaluation returns.
|
|
||||||
*
|
|
||||||
* See [[unwrapResult]], which will throw if the function returned an error, or
|
|
||||||
* return the result handle directly. If evaluation returned a handle containing
|
|
||||||
* a promise, use [[resolvePromise]] to convert it to a native promise and
|
|
||||||
* [[executePendingJobs]] to finish evaluating the promise.
|
|
||||||
*
|
|
||||||
* *Note*: to protect against infinite loops, provide an interrupt handler to
|
|
||||||
* [[setInterruptHandler]]. You can use [[shouldInterruptAfterDeadline]] to
|
|
||||||
* create a time-based deadline.
|
|
||||||
*
|
|
||||||
* @returns The last statement's value. If the code threw synchronously,
|
|
||||||
* `result.error` will be a handle to the exception. If execution was
|
|
||||||
* interrupted, the error will have name `InternalError` and message
|
|
||||||
* `interrupted`.
|
|
||||||
*/
|
|
||||||
evalCode(code: string, filename?: string,
|
|
||||||
/**
|
|
||||||
* If no options are passed, a heuristic will be used to detect if `code` is
|
|
||||||
* an ES module.
|
|
||||||
*
|
|
||||||
* See [[EvalFlags]] for number semantics.
|
|
||||||
*/
|
|
||||||
options?: number | ContextEvalOptions): VmCallResult<QuickJSHandle>;
|
|
||||||
/**
|
|
||||||
* Throw an error in the VM, interrupted whatever current execution is in progress when execution resumes.
|
|
||||||
* @experimental
|
|
||||||
*/
|
|
||||||
throw(error: Error | QuickJSHandle): any;
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
protected borrowPropertyKey(key: QuickJSPropertyKey): QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
getMemory(rt: JSRuntimePointer): ContextMemory;
|
|
||||||
/**
|
|
||||||
* Dump a JSValue to Javascript in a best-effort fashion.
|
|
||||||
* Returns `handle.toString()` if it cannot be serialized to JSON.
|
|
||||||
*/
|
|
||||||
dump(handle: QuickJSHandle): any;
|
|
||||||
/**
|
|
||||||
* Unwrap a SuccessOrFail result such as a [[VmCallResult]] or a
|
|
||||||
* [[ExecutePendingJobsResult]], where the fail branch contains a handle to a QuickJS error value.
|
|
||||||
* If the result is a success, returns the value.
|
|
||||||
* If the result is an error, converts the error to a native object and throws the error.
|
|
||||||
*/
|
|
||||||
unwrapResult<T>(result: SuccessOrFail<T, QuickJSHandle>): T;
|
|
||||||
/** @private */
|
|
||||||
protected fnNextId: number;
|
|
||||||
/** @private */
|
|
||||||
protected fnMaps: Map<number, Map<number, VmFunctionImplementation<QuickJSHandle>>>;
|
|
||||||
/** @private */
|
|
||||||
protected getFunction(fn_id: number): VmFunctionImplementation<QuickJSHandle> | undefined;
|
|
||||||
/** @private */
|
|
||||||
protected setFunction(fn_id: number, handle: VmFunctionImplementation<QuickJSHandle>): Map<number, VmFunctionImplementation<QuickJSHandle>>;
|
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
private cToHostCallbacks;
|
|
||||||
private errorToHandle;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
691
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/context.js
generated
vendored
691
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/context.js
generated
vendored
@@ -1,691 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.QuickJSContext = void 0;
|
|
||||||
const debug_1 = require("./debug");
|
|
||||||
const deferred_promise_1 = require("./deferred-promise");
|
|
||||||
const errors_1 = require("./errors");
|
|
||||||
const lifetime_1 = require("./lifetime");
|
|
||||||
const memory_1 = require("./memory");
|
|
||||||
const types_1 = require("./types");
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
class ContextMemory extends memory_1.ModuleMemory {
|
|
||||||
/** @private */
|
|
||||||
constructor(args) {
|
|
||||||
super(args.module);
|
|
||||||
this.scope = new lifetime_1.Scope();
|
|
||||||
this.copyJSValue = (ptr) => {
|
|
||||||
return this.ffi.QTS_DupValuePointer(this.ctx.value, ptr);
|
|
||||||
};
|
|
||||||
this.freeJSValue = (ptr) => {
|
|
||||||
this.ffi.QTS_FreeValuePointer(this.ctx.value, ptr);
|
|
||||||
};
|
|
||||||
args.ownedLifetimes?.forEach((lifetime) => this.scope.manage(lifetime));
|
|
||||||
this.owner = args.owner;
|
|
||||||
this.module = args.module;
|
|
||||||
this.ffi = args.ffi;
|
|
||||||
this.rt = args.rt;
|
|
||||||
this.ctx = this.scope.manage(args.ctx);
|
|
||||||
}
|
|
||||||
get alive() {
|
|
||||||
return this.scope.alive;
|
|
||||||
}
|
|
||||||
dispose() {
|
|
||||||
return this.scope.dispose();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Track `lifetime` so that it is disposed when this scope is disposed.
|
|
||||||
*/
|
|
||||||
manage(lifetime) {
|
|
||||||
return this.scope.manage(lifetime);
|
|
||||||
}
|
|
||||||
consumeJSCharPointer(ptr) {
|
|
||||||
const str = this.module.UTF8ToString(ptr);
|
|
||||||
this.ffi.QTS_FreeCString(this.ctx.value, ptr);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
heapValueHandle(ptr) {
|
|
||||||
return new lifetime_1.Lifetime(ptr, this.copyJSValue, this.freeJSValue, this.owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* QuickJSContext wraps a QuickJS Javascript context (JSContext*) within a
|
|
||||||
* runtime. The contexts within the same runtime may exchange objects freely.
|
|
||||||
* You can think of separate runtimes like different domains in a browser, and
|
|
||||||
* the contexts within a runtime like the different windows open to the same
|
|
||||||
* domain. The {@link runtime} references the context's runtime.
|
|
||||||
*
|
|
||||||
* This class's methods return {@link QuickJSHandle}, which wrap C pointers (JSValue*).
|
|
||||||
* It's the caller's responsibility to call `.dispose()` on any
|
|
||||||
* handles you create to free memory once you're done with the handle.
|
|
||||||
*
|
|
||||||
* Use {@link QuickJSRuntime.newContext} or {@link QuickJSWASMModule.newContext}
|
|
||||||
* to create a new QuickJSContext.
|
|
||||||
*
|
|
||||||
* Create QuickJS values inside the interpreter with methods like
|
|
||||||
* [[newNumber]], [[newString]], [[newArray]], [[newObject]],
|
|
||||||
* [[newFunction]], and [[newPromise]].
|
|
||||||
*
|
|
||||||
* Call [[setProp]] or [[defineProp]] to customize objects. Use those methods
|
|
||||||
* with [[global]] to expose the values you create to the interior of the
|
|
||||||
* interpreter, so they can be used in [[evalCode]].
|
|
||||||
*
|
|
||||||
* Use [[evalCode]] or [[callFunction]] to execute Javascript inside the VM. If
|
|
||||||
* you're using asynchronous code inside the QuickJSContext, you may need to also
|
|
||||||
* call [[executePendingJobs]]. Executing code inside the runtime returns a
|
|
||||||
* result object representing successful execution or an error. You must dispose
|
|
||||||
* of any such results to avoid leaking memory inside the VM.
|
|
||||||
*
|
|
||||||
* Implement memory and CPU constraints at the runtime level, using [[runtime]].
|
|
||||||
* See {@link QuickJSRuntime} for more information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// TODO: Manage own callback registration
|
|
||||||
class QuickJSContext {
|
|
||||||
/**
|
|
||||||
* Use {@link QuickJS.createVm} to create a QuickJSContext instance.
|
|
||||||
*/
|
|
||||||
constructor(args) {
|
|
||||||
/** @private */
|
|
||||||
this._undefined = undefined;
|
|
||||||
/** @private */
|
|
||||||
this._null = undefined;
|
|
||||||
/** @private */
|
|
||||||
this._false = undefined;
|
|
||||||
/** @private */
|
|
||||||
this._true = undefined;
|
|
||||||
/** @private */
|
|
||||||
this._global = undefined;
|
|
||||||
/** @private */
|
|
||||||
this._BigInt = undefined;
|
|
||||||
/** @private */
|
|
||||||
this.fnNextId = -32768; // min value of signed 16bit int used by Quickjs
|
|
||||||
/** @private */
|
|
||||||
this.fnMaps = new Map();
|
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
this.cToHostCallbacks = {
|
|
||||||
callFunction: (ctx, this_ptr, argc, argv, fn_id) => {
|
|
||||||
if (ctx !== this.ctx.value) {
|
|
||||||
throw new Error("QuickJSContext instance received C -> JS call with mismatched ctx");
|
|
||||||
}
|
|
||||||
const fn = this.getFunction(fn_id);
|
|
||||||
if (!fn) {
|
|
||||||
// this "throw" is not catch-able from the TS side. could we somehow handle this higher up?
|
|
||||||
throw new Error(`QuickJSContext had no callback with id ${fn_id}`);
|
|
||||||
}
|
|
||||||
return lifetime_1.Scope.withScopeMaybeAsync(this, function* (awaited, scope) {
|
|
||||||
const thisHandle = scope.manage(new lifetime_1.WeakLifetime(this_ptr, this.memory.copyJSValue, this.memory.freeJSValue, this.runtime));
|
|
||||||
const argHandles = new Array(argc);
|
|
||||||
for (let i = 0; i < argc; i++) {
|
|
||||||
const ptr = this.ffi.QTS_ArgvGetJSValueConstPointer(argv, i);
|
|
||||||
argHandles[i] = scope.manage(new lifetime_1.WeakLifetime(ptr, this.memory.copyJSValue, this.memory.freeJSValue, this.runtime));
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = yield* awaited(fn.apply(thisHandle, argHandles));
|
|
||||||
if (result) {
|
|
||||||
if ("error" in result && result.error) {
|
|
||||||
(0, debug_1.debugLog)("throw error", result.error);
|
|
||||||
throw result.error;
|
|
||||||
}
|
|
||||||
const handle = scope.manage(result instanceof lifetime_1.Lifetime ? result : result.value);
|
|
||||||
return this.ffi.QTS_DupValuePointer(this.ctx.value, handle.value);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
return this.errorToHandle(error).consume((errorHandle) => this.ffi.QTS_Throw(this.ctx.value, errorHandle.value));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
this.runtime = args.runtime;
|
|
||||||
this.module = args.module;
|
|
||||||
this.ffi = args.ffi;
|
|
||||||
this.rt = args.rt;
|
|
||||||
this.ctx = args.ctx;
|
|
||||||
this.memory = new ContextMemory({
|
|
||||||
...args,
|
|
||||||
owner: this.runtime,
|
|
||||||
});
|
|
||||||
args.callbacks.setContextCallbacks(this.ctx.value, this.cToHostCallbacks);
|
|
||||||
this.dump = this.dump.bind(this);
|
|
||||||
this.getString = this.getString.bind(this);
|
|
||||||
this.getNumber = this.getNumber.bind(this);
|
|
||||||
this.resolvePromise = this.resolvePromise.bind(this);
|
|
||||||
}
|
|
||||||
// @implement Disposable ----------------------------------------------------
|
|
||||||
get alive() {
|
|
||||||
return this.memory.alive;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Dispose of this VM's underlying resources.
|
|
||||||
*
|
|
||||||
* @throws Calling this method without disposing of all created handles
|
|
||||||
* will result in an error.
|
|
||||||
*/
|
|
||||||
dispose() {
|
|
||||||
this.memory.dispose();
|
|
||||||
}
|
|
||||||
// Globals ------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined).
|
|
||||||
*/
|
|
||||||
get undefined() {
|
|
||||||
if (this._undefined) {
|
|
||||||
return this._undefined;
|
|
||||||
}
|
|
||||||
// Undefined is a constant, immutable value in QuickJS.
|
|
||||||
const ptr = this.ffi.QTS_GetUndefined();
|
|
||||||
return (this._undefined = new lifetime_1.StaticLifetime(ptr));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null).
|
|
||||||
*/
|
|
||||||
get null() {
|
|
||||||
if (this._null) {
|
|
||||||
return this._null;
|
|
||||||
}
|
|
||||||
// Null is a constant, immutable value in QuickJS.
|
|
||||||
const ptr = this.ffi.QTS_GetNull();
|
|
||||||
return (this._null = new lifetime_1.StaticLifetime(ptr));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* [`true`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/true).
|
|
||||||
*/
|
|
||||||
get true() {
|
|
||||||
if (this._true) {
|
|
||||||
return this._true;
|
|
||||||
}
|
|
||||||
// True is a constant, immutable value in QuickJS.
|
|
||||||
const ptr = this.ffi.QTS_GetTrue();
|
|
||||||
return (this._true = new lifetime_1.StaticLifetime(ptr));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* [`false`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/false).
|
|
||||||
*/
|
|
||||||
get false() {
|
|
||||||
if (this._false) {
|
|
||||||
return this._false;
|
|
||||||
}
|
|
||||||
// False is a constant, immutable value in QuickJS.
|
|
||||||
const ptr = this.ffi.QTS_GetFalse();
|
|
||||||
return (this._false = new lifetime_1.StaticLifetime(ptr));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* [`global`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects).
|
|
||||||
* A handle to the global object inside the interpreter.
|
|
||||||
* You can set properties to create global variables.
|
|
||||||
*/
|
|
||||||
get global() {
|
|
||||||
if (this._global) {
|
|
||||||
return this._global;
|
|
||||||
}
|
|
||||||
// The global is a JSValue, but since it's lifetime is as long as the VM's,
|
|
||||||
// we should manage it.
|
|
||||||
const ptr = this.ffi.QTS_GetGlobalObject(this.ctx.value);
|
|
||||||
// Automatically clean up this reference when we dispose
|
|
||||||
this.memory.manage(this.memory.heapValueHandle(ptr));
|
|
||||||
// This isn't technically a static lifetime, but since it has the same
|
|
||||||
// lifetime as the VM, it's okay to fake one since when the VM is
|
|
||||||
// disposed, no other functions will accept the value.
|
|
||||||
this._global = new lifetime_1.StaticLifetime(ptr, this.runtime);
|
|
||||||
return this._global;
|
|
||||||
}
|
|
||||||
// New values ---------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* Converts a Javascript number into a QuickJS value.
|
|
||||||
*/
|
|
||||||
newNumber(num) {
|
|
||||||
return this.memory.heapValueHandle(this.ffi.QTS_NewFloat64(this.ctx.value, num));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) value.
|
|
||||||
*/
|
|
||||||
newString(str) {
|
|
||||||
const ptr = this.memory
|
|
||||||
.newHeapCharPointer(str)
|
|
||||||
.consume((charHandle) => this.ffi.QTS_NewString(this.ctx.value, charHandle.value));
|
|
||||||
return this.memory.heapValueHandle(ptr);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) value.
|
|
||||||
* No two symbols created with this function will be the same value.
|
|
||||||
*/
|
|
||||||
newUniqueSymbol(description) {
|
|
||||||
const key = (typeof description === "symbol" ? description.description : description) ?? "";
|
|
||||||
const ptr = this.memory
|
|
||||||
.newHeapCharPointer(key)
|
|
||||||
.consume((charHandle) => this.ffi.QTS_NewSymbol(this.ctx.value, charHandle.value, 0));
|
|
||||||
return this.memory.heapValueHandle(ptr);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get a symbol from the [global registry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#shared_symbols_in_the_global_symbol_registry) for the given key.
|
|
||||||
* All symbols created with the same key will be the same value.
|
|
||||||
*/
|
|
||||||
newSymbolFor(key) {
|
|
||||||
const description = (typeof key === "symbol" ? key.description : key) ?? "";
|
|
||||||
const ptr = this.memory
|
|
||||||
.newHeapCharPointer(description)
|
|
||||||
.consume((charHandle) => this.ffi.QTS_NewSymbol(this.ctx.value, charHandle.value, 1));
|
|
||||||
return this.memory.heapValueHandle(ptr);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Create a QuickJS [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) value.
|
|
||||||
*/
|
|
||||||
newBigInt(num) {
|
|
||||||
if (!this._BigInt) {
|
|
||||||
const bigIntHandle = this.getProp(this.global, "BigInt");
|
|
||||||
this.memory.manage(bigIntHandle);
|
|
||||||
this._BigInt = new lifetime_1.StaticLifetime(bigIntHandle.value, this.runtime);
|
|
||||||
}
|
|
||||||
const bigIntHandle = this._BigInt;
|
|
||||||
const asString = String(num);
|
|
||||||
return this.newString(asString).consume((handle) => this.unwrapResult(this.callFunction(bigIntHandle, this.undefined, handle)));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* `{}`.
|
|
||||||
* Create a new QuickJS [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer).
|
|
||||||
*
|
|
||||||
* @param prototype - Like [`Object.create`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create).
|
|
||||||
*/
|
|
||||||
newObject(prototype) {
|
|
||||||
if (prototype) {
|
|
||||||
this.runtime.assertOwned(prototype);
|
|
||||||
}
|
|
||||||
const ptr = prototype
|
|
||||||
? this.ffi.QTS_NewObjectProto(this.ctx.value, prototype.value)
|
|
||||||
: this.ffi.QTS_NewObject(this.ctx.value);
|
|
||||||
return this.memory.heapValueHandle(ptr);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* `[]`.
|
|
||||||
* Create a new QuickJS [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
|
|
||||||
*/
|
|
||||||
newArray() {
|
|
||||||
const ptr = this.ffi.QTS_NewArray(this.ctx.value);
|
|
||||||
return this.memory.heapValueHandle(ptr);
|
|
||||||
}
|
|
||||||
newPromise(value) {
|
|
||||||
const deferredPromise = lifetime_1.Scope.withScope((scope) => {
|
|
||||||
const mutablePointerArray = scope.manage(this.memory.newMutablePointerArray(2));
|
|
||||||
const promisePtr = this.ffi.QTS_NewPromiseCapability(this.ctx.value, mutablePointerArray.value.ptr);
|
|
||||||
const promiseHandle = this.memory.heapValueHandle(promisePtr);
|
|
||||||
const [resolveHandle, rejectHandle] = Array.from(mutablePointerArray.value.typedArray).map((jsvaluePtr) => this.memory.heapValueHandle(jsvaluePtr));
|
|
||||||
return new deferred_promise_1.QuickJSDeferredPromise({
|
|
||||||
context: this,
|
|
||||||
promiseHandle,
|
|
||||||
resolveHandle,
|
|
||||||
rejectHandle,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (value && typeof value === "function") {
|
|
||||||
value = new Promise(value);
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
Promise.resolve(value).then(deferredPromise.resolve, (error) => error instanceof lifetime_1.Lifetime
|
|
||||||
? deferredPromise.reject(error)
|
|
||||||
: this.newError(error).consume(deferredPromise.reject));
|
|
||||||
}
|
|
||||||
return deferredPromise;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Convert a Javascript function into a QuickJS function value.
|
|
||||||
* See [[VmFunctionImplementation]] for more details.
|
|
||||||
*
|
|
||||||
* A [[VmFunctionImplementation]] should not free its arguments or its return
|
|
||||||
* value. A VmFunctionImplementation should also not retain any references to
|
|
||||||
* its return value.
|
|
||||||
*
|
|
||||||
* To implement an async function, create a promise with [[newPromise]], then
|
|
||||||
* return the deferred promise handle from `deferred.handle` from your
|
|
||||||
* function implementation:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* const deferred = vm.newPromise()
|
|
||||||
* someNativeAsyncFunction().then(deferred.resolve)
|
|
||||||
* return deferred.handle
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
newFunction(name, fn) {
|
|
||||||
const fnId = ++this.fnNextId;
|
|
||||||
this.setFunction(fnId, fn);
|
|
||||||
return this.memory.heapValueHandle(this.ffi.QTS_NewFunction(this.ctx.value, fnId, name));
|
|
||||||
}
|
|
||||||
newError(error) {
|
|
||||||
const errorHandle = this.memory.heapValueHandle(this.ffi.QTS_NewError(this.ctx.value));
|
|
||||||
if (error && typeof error === "object") {
|
|
||||||
if (error.name !== undefined) {
|
|
||||||
this.newString(error.name).consume((handle) => this.setProp(errorHandle, "name", handle));
|
|
||||||
}
|
|
||||||
if (error.message !== undefined) {
|
|
||||||
this.newString(error.message).consume((handle) => this.setProp(errorHandle, "message", handle));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (typeof error === "string") {
|
|
||||||
this.newString(error).consume((handle) => this.setProp(errorHandle, "message", handle));
|
|
||||||
}
|
|
||||||
else if (error !== undefined) {
|
|
||||||
// This isn't supported in the type signature but maybe it will make life easier.
|
|
||||||
this.newString(String(error)).consume((handle) => this.setProp(errorHandle, "message", handle));
|
|
||||||
}
|
|
||||||
return errorHandle;
|
|
||||||
}
|
|
||||||
// Read values --------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* `typeof` operator. **Not** [standards compliant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof).
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* Does not support BigInt values correctly.
|
|
||||||
*/
|
|
||||||
typeof(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
return this.memory.consumeHeapCharPointer(this.ffi.QTS_Typeof(this.ctx.value, handle.value));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Converts `handle` into a Javascript number.
|
|
||||||
* @returns `NaN` on error, otherwise a `number`.
|
|
||||||
*/
|
|
||||||
getNumber(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
return this.ffi.QTS_GetFloat64(this.ctx.value, handle.value);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Converts `handle` to a Javascript string.
|
|
||||||
*/
|
|
||||||
getString(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
return this.memory.consumeJSCharPointer(this.ffi.QTS_GetString(this.ctx.value, handle.value));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Converts `handle` into a Javascript symbol. If the symbol is in the global
|
|
||||||
* registry in the guest, it will be created with Symbol.for on the host.
|
|
||||||
*/
|
|
||||||
getSymbol(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
const key = this.memory.consumeJSCharPointer(this.ffi.QTS_GetSymbolDescriptionOrKey(this.ctx.value, handle.value));
|
|
||||||
const isGlobal = this.ffi.QTS_IsGlobalSymbol(this.ctx.value, handle.value);
|
|
||||||
return isGlobal ? Symbol.for(key) : Symbol(key);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Converts `handle` to a Javascript bigint.
|
|
||||||
*/
|
|
||||||
getBigInt(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
const asString = this.getString(handle);
|
|
||||||
return BigInt(asString);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* `Promise.resolve(value)`.
|
|
||||||
* Convert a handle containing a Promise-like value inside the VM into an
|
|
||||||
* actual promise on the host.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* You may need to call [[executePendingJobs]] to ensure that the promise is resolved.
|
|
||||||
*
|
|
||||||
* @param promiseLikeHandle - A handle to a Promise-like value with a `.then(onSuccess, onError)` method.
|
|
||||||
*/
|
|
||||||
resolvePromise(promiseLikeHandle) {
|
|
||||||
this.runtime.assertOwned(promiseLikeHandle);
|
|
||||||
const vmResolveResult = lifetime_1.Scope.withScope((scope) => {
|
|
||||||
const vmPromise = scope.manage(this.getProp(this.global, "Promise"));
|
|
||||||
const vmPromiseResolve = scope.manage(this.getProp(vmPromise, "resolve"));
|
|
||||||
return this.callFunction(vmPromiseResolve, vmPromise, promiseLikeHandle);
|
|
||||||
});
|
|
||||||
if (vmResolveResult.error) {
|
|
||||||
return Promise.resolve(vmResolveResult);
|
|
||||||
}
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
lifetime_1.Scope.withScope((scope) => {
|
|
||||||
const resolveHandle = scope.manage(this.newFunction("resolve", (value) => {
|
|
||||||
resolve({ value: value && value.dup() });
|
|
||||||
}));
|
|
||||||
const rejectHandle = scope.manage(this.newFunction("reject", (error) => {
|
|
||||||
resolve({ error: error && error.dup() });
|
|
||||||
}));
|
|
||||||
const promiseHandle = scope.manage(vmResolveResult.value);
|
|
||||||
const promiseThenHandle = scope.manage(this.getProp(promiseHandle, "then"));
|
|
||||||
this.unwrapResult(this.callFunction(promiseThenHandle, promiseHandle, resolveHandle, rejectHandle)).dispose();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Properties ---------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* `handle[key]`.
|
|
||||||
* Get a property from a JSValue.
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string (which will be converted automatically).
|
|
||||||
*/
|
|
||||||
getProp(handle, key) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
const ptr = this.borrowPropertyKey(key).consume((quickJSKey) => this.ffi.QTS_GetProp(this.ctx.value, handle.value, quickJSKey.value));
|
|
||||||
const result = this.memory.heapValueHandle(ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* `handle[key] = value`.
|
|
||||||
* Set a property on a JSValue.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* Note that the QuickJS authors recommend using [[defineProp]] to define new
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string or number (which will be converted automatically to a JSValue).
|
|
||||||
*/
|
|
||||||
setProp(handle, key, value) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
// free newly allocated value if key was a string or number. No-op if string was already
|
|
||||||
// a QuickJS handle.
|
|
||||||
this.borrowPropertyKey(key).consume((quickJSKey) => this.ffi.QTS_SetProp(this.ctx.value, handle.value, quickJSKey.value, value.value));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* [`Object.defineProperty(handle, key, descriptor)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
|
|
||||||
*
|
|
||||||
* @param key - The property may be specified as a JSValue handle, or as a
|
|
||||||
* Javascript string or number (which will be converted automatically to a JSValue).
|
|
||||||
*/
|
|
||||||
defineProp(handle, key, descriptor) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
lifetime_1.Scope.withScope((scope) => {
|
|
||||||
const quickJSKey = scope.manage(this.borrowPropertyKey(key));
|
|
||||||
const value = descriptor.value || this.undefined;
|
|
||||||
const configurable = Boolean(descriptor.configurable);
|
|
||||||
const enumerable = Boolean(descriptor.enumerable);
|
|
||||||
const hasValue = Boolean(descriptor.value);
|
|
||||||
const get = descriptor.get
|
|
||||||
? scope.manage(this.newFunction(descriptor.get.name, descriptor.get))
|
|
||||||
: this.undefined;
|
|
||||||
const set = descriptor.set
|
|
||||||
? scope.manage(this.newFunction(descriptor.set.name, descriptor.set))
|
|
||||||
: this.undefined;
|
|
||||||
this.ffi.QTS_DefineProp(this.ctx.value, handle.value, quickJSKey.value, value.value, get.value, set.value, configurable, enumerable, hasValue);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Evaluation ---------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* [`func.call(thisVal, ...args)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call).
|
|
||||||
* Call a JSValue as a function.
|
|
||||||
*
|
|
||||||
* See [[unwrapResult]], which will throw if the function returned an error, or
|
|
||||||
* return the result handle directly. If evaluation returned a handle containing
|
|
||||||
* a promise, use [[resolvePromise]] to convert it to a native promise and
|
|
||||||
* [[executePendingJobs]] to finish evaluating the promise.
|
|
||||||
*
|
|
||||||
* @returns A result. If the function threw synchronously, `result.error` be a
|
|
||||||
* handle to the exception. Otherwise `result.value` will be a handle to the
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
callFunction(func, thisVal, ...args) {
|
|
||||||
this.runtime.assertOwned(func);
|
|
||||||
const resultPtr = this.memory
|
|
||||||
.toPointerArray(args)
|
|
||||||
.consume((argsArrayPtr) => this.ffi.QTS_Call(this.ctx.value, func.value, thisVal.value, args.length, argsArrayPtr.value));
|
|
||||||
const errorPtr = this.ffi.QTS_ResolveException(this.ctx.value, resultPtr);
|
|
||||||
if (errorPtr) {
|
|
||||||
this.ffi.QTS_FreeValuePointer(this.ctx.value, resultPtr);
|
|
||||||
return { error: this.memory.heapValueHandle(errorPtr) };
|
|
||||||
}
|
|
||||||
return { value: this.memory.heapValueHandle(resultPtr) };
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Like [`eval(code)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Description).
|
|
||||||
* Evaluates the Javascript source `code` in the global scope of this VM.
|
|
||||||
* When working with async code, you many need to call [[executePendingJobs]]
|
|
||||||
* to execute callbacks pending after synchronous evaluation returns.
|
|
||||||
*
|
|
||||||
* See [[unwrapResult]], which will throw if the function returned an error, or
|
|
||||||
* return the result handle directly. If evaluation returned a handle containing
|
|
||||||
* a promise, use [[resolvePromise]] to convert it to a native promise and
|
|
||||||
* [[executePendingJobs]] to finish evaluating the promise.
|
|
||||||
*
|
|
||||||
* *Note*: to protect against infinite loops, provide an interrupt handler to
|
|
||||||
* [[setInterruptHandler]]. You can use [[shouldInterruptAfterDeadline]] to
|
|
||||||
* create a time-based deadline.
|
|
||||||
*
|
|
||||||
* @returns The last statement's value. If the code threw synchronously,
|
|
||||||
* `result.error` will be a handle to the exception. If execution was
|
|
||||||
* interrupted, the error will have name `InternalError` and message
|
|
||||||
* `interrupted`.
|
|
||||||
*/
|
|
||||||
evalCode(code, filename = "eval.js",
|
|
||||||
/**
|
|
||||||
* If no options are passed, a heuristic will be used to detect if `code` is
|
|
||||||
* an ES module.
|
|
||||||
*
|
|
||||||
* See [[EvalFlags]] for number semantics.
|
|
||||||
*/
|
|
||||||
options) {
|
|
||||||
const detectModule = (options === undefined ? 1 : 0);
|
|
||||||
const flags = (0, types_1.evalOptionsToFlags)(options);
|
|
||||||
const resultPtr = this.memory
|
|
||||||
.newHeapCharPointer(code)
|
|
||||||
.consume((charHandle) => this.ffi.QTS_Eval(this.ctx.value, charHandle.value, filename, detectModule, flags));
|
|
||||||
const errorPtr = this.ffi.QTS_ResolveException(this.ctx.value, resultPtr);
|
|
||||||
if (errorPtr) {
|
|
||||||
this.ffi.QTS_FreeValuePointer(this.ctx.value, resultPtr);
|
|
||||||
return { error: this.memory.heapValueHandle(errorPtr) };
|
|
||||||
}
|
|
||||||
return { value: this.memory.heapValueHandle(resultPtr) };
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Throw an error in the VM, interrupted whatever current execution is in progress when execution resumes.
|
|
||||||
* @experimental
|
|
||||||
*/
|
|
||||||
throw(error) {
|
|
||||||
return this.errorToHandle(error).consume((handle) => this.ffi.QTS_Throw(this.ctx.value, handle.value));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
borrowPropertyKey(key) {
|
|
||||||
if (typeof key === "number") {
|
|
||||||
return this.newNumber(key);
|
|
||||||
}
|
|
||||||
if (typeof key === "string") {
|
|
||||||
return this.newString(key);
|
|
||||||
}
|
|
||||||
// key is already a JSValue, but we're borrowing it. Return a static handle
|
|
||||||
// for internal use only.
|
|
||||||
return new lifetime_1.StaticLifetime(key.value, this.runtime);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
getMemory(rt) {
|
|
||||||
if (rt === this.rt.value) {
|
|
||||||
return this.memory;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Error("Private API. Cannot get memory from a different runtime");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Utilities ----------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* Dump a JSValue to Javascript in a best-effort fashion.
|
|
||||||
* Returns `handle.toString()` if it cannot be serialized to JSON.
|
|
||||||
*/
|
|
||||||
dump(handle) {
|
|
||||||
this.runtime.assertOwned(handle);
|
|
||||||
const type = this.typeof(handle);
|
|
||||||
if (type === "string") {
|
|
||||||
return this.getString(handle);
|
|
||||||
}
|
|
||||||
else if (type === "number") {
|
|
||||||
return this.getNumber(handle);
|
|
||||||
}
|
|
||||||
else if (type === "bigint") {
|
|
||||||
return this.getBigInt(handle);
|
|
||||||
}
|
|
||||||
else if (type === "undefined") {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
else if (type === "symbol") {
|
|
||||||
return this.getSymbol(handle);
|
|
||||||
}
|
|
||||||
const str = this.memory.consumeJSCharPointer(this.ffi.QTS_Dump(this.ctx.value, handle.value));
|
|
||||||
try {
|
|
||||||
return JSON.parse(str);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Unwrap a SuccessOrFail result such as a [[VmCallResult]] or a
|
|
||||||
* [[ExecutePendingJobsResult]], where the fail branch contains a handle to a QuickJS error value.
|
|
||||||
* If the result is a success, returns the value.
|
|
||||||
* If the result is an error, converts the error to a native object and throws the error.
|
|
||||||
*/
|
|
||||||
unwrapResult(result) {
|
|
||||||
if (result.error) {
|
|
||||||
const context = "context" in result.error ? result.error.context : this;
|
|
||||||
const cause = result.error.consume((error) => this.dump(error));
|
|
||||||
if (cause && typeof cause === "object" && typeof cause.message === "string") {
|
|
||||||
const { message, name, stack } = cause;
|
|
||||||
const exception = new errors_1.QuickJSUnwrapError("");
|
|
||||||
const hostStack = exception.stack;
|
|
||||||
if (typeof name === "string") {
|
|
||||||
exception.name = cause.name;
|
|
||||||
}
|
|
||||||
if (typeof stack === "string") {
|
|
||||||
exception.stack = `${name}: ${message}\n${cause.stack}Host: ${hostStack}`;
|
|
||||||
}
|
|
||||||
Object.assign(exception, { cause, context, message });
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
throw new errors_1.QuickJSUnwrapError(cause, context);
|
|
||||||
}
|
|
||||||
return result.value;
|
|
||||||
}
|
|
||||||
/** @private */
|
|
||||||
getFunction(fn_id) {
|
|
||||||
const map_id = fn_id >> 8;
|
|
||||||
const fnMap = this.fnMaps.get(map_id);
|
|
||||||
if (!fnMap) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return fnMap.get(fn_id);
|
|
||||||
}
|
|
||||||
/** @private */
|
|
||||||
setFunction(fn_id, handle) {
|
|
||||||
const map_id = fn_id >> 8;
|
|
||||||
let fnMap = this.fnMaps.get(map_id);
|
|
||||||
if (!fnMap) {
|
|
||||||
fnMap = new Map();
|
|
||||||
this.fnMaps.set(map_id, fnMap);
|
|
||||||
}
|
|
||||||
return fnMap.set(fn_id, handle);
|
|
||||||
}
|
|
||||||
errorToHandle(error) {
|
|
||||||
if (error instanceof lifetime_1.Lifetime) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return this.newError(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSContext = QuickJSContext;
|
|
||||||
//# sourceMappingURL=context.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
5
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/debug.d.ts
generated
vendored
5
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/debug.d.ts
generated
vendored
@@ -1,5 +0,0 @@
|
|||||||
export declare const QTS_DEBUG: boolean;
|
|
||||||
export declare let debugLog: {
|
|
||||||
(...data: any[]): void;
|
|
||||||
(message?: any, ...optionalParams: any[]): void;
|
|
||||||
};
|
|
||||||
6
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/debug.js
generated
vendored
6
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/debug.js
generated
vendored
@@ -1,6 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.debugLog = exports.QTS_DEBUG = void 0;
|
|
||||||
exports.QTS_DEBUG = false || Boolean(typeof process === "object" && process.env.QTS_DEBUG);
|
|
||||||
exports.debugLog = exports.QTS_DEBUG ? console.log.bind(console) : () => { };
|
|
||||||
//# sourceMappingURL=debug.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../ts/debug.ts"],"names":[],"mappings":";;;AAAa,QAAA,SAAS,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AACpF,QAAA,QAAQ,GAAG,iBAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA","sourcesContent":["export const QTS_DEBUG = false || Boolean(typeof process === \"object\" && process.env.QTS_DEBUG)\nexport let debugLog = QTS_DEBUG ? console.log.bind(console) : () => {}\n"]}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import type { Disposable } from "./lifetime";
|
|
||||||
import type { QuickJSHandle } from "./types";
|
|
||||||
import type { QuickJSRuntime } from "./runtime";
|
|
||||||
import type { QuickJSContext } from "./context";
|
|
||||||
export type { PromiseExecutor } from "./types";
|
|
||||||
/**
|
|
||||||
* QuickJSDeferredPromise wraps a QuickJS promise [[handle]] and allows
|
|
||||||
* [[resolve]]ing or [[reject]]ing that promise. Use it to bridge asynchronous
|
|
||||||
* code on the host to APIs inside a QuickJSContext.
|
|
||||||
*
|
|
||||||
* Managing the lifetime of promises is tricky. There are three
|
|
||||||
* [[QuickJSHandle]]s inside of each deferred promise object: (1) the promise
|
|
||||||
* itself, (2) the `resolve` callback, and (3) the `reject` callback.
|
|
||||||
*
|
|
||||||
* - If the promise will be fulfilled before the end of it's [[owner]]'s lifetime,
|
|
||||||
* the only cleanup necessary is `deferred.handle.dispose()`, because
|
|
||||||
* calling [[resolve]] or [[reject]] will dispose of both callbacks automatically.
|
|
||||||
*
|
|
||||||
* - As the return value of a [[VmFunctionImplementation]], return [[handle]],
|
|
||||||
* and ensure that either [[resolve]] or [[reject]] will be called. No other
|
|
||||||
* clean-up is necessary.
|
|
||||||
*
|
|
||||||
* - In other cases, call [[dispose]], which will dispose [[handle]] as well as the
|
|
||||||
* QuickJS handles that back [[resolve]] and [[reject]]. For this object,
|
|
||||||
* [[dispose]] is idempotent.
|
|
||||||
*/
|
|
||||||
export declare class QuickJSDeferredPromise implements Disposable {
|
|
||||||
owner: QuickJSRuntime;
|
|
||||||
context: QuickJSContext;
|
|
||||||
/**
|
|
||||||
* A handle of the Promise instance inside the QuickJSContext.
|
|
||||||
* You must dispose [[handle]] or the entire QuickJSDeferredPromise once you
|
|
||||||
* are finished with it.
|
|
||||||
*/
|
|
||||||
handle: QuickJSHandle;
|
|
||||||
/**
|
|
||||||
* A native promise that will resolve once this deferred is settled.
|
|
||||||
*/
|
|
||||||
settled: Promise<void>;
|
|
||||||
private resolveHandle;
|
|
||||||
private rejectHandle;
|
|
||||||
private onSettled;
|
|
||||||
/**
|
|
||||||
* Use [[QuickJSContext.newPromise]] to create a new promise instead of calling
|
|
||||||
* this constructor directly.
|
|
||||||
* @unstable
|
|
||||||
*/
|
|
||||||
constructor(args: {
|
|
||||||
context: QuickJSContext;
|
|
||||||
promiseHandle: QuickJSHandle;
|
|
||||||
resolveHandle: QuickJSHandle;
|
|
||||||
rejectHandle: QuickJSHandle;
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* Resolve [[handle]] with the given value, if any.
|
|
||||||
* Calling this method after calling [[dispose]] is a no-op.
|
|
||||||
*
|
|
||||||
* Note that after resolving a promise, you may need to call
|
|
||||||
* [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's
|
|
||||||
* callbacks.
|
|
||||||
*/
|
|
||||||
resolve: (value?: QuickJSHandle) => void;
|
|
||||||
/**
|
|
||||||
* Reject [[handle]] with the given value, if any.
|
|
||||||
* Calling this method after calling [[dispose]] is a no-op.
|
|
||||||
*
|
|
||||||
* Note that after rejecting a promise, you may need to call
|
|
||||||
* [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's
|
|
||||||
* callbacks.
|
|
||||||
*/
|
|
||||||
reject: (value?: QuickJSHandle) => void;
|
|
||||||
get alive(): boolean;
|
|
||||||
dispose: () => void;
|
|
||||||
private disposeResolvers;
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.QuickJSDeferredPromise = void 0;
|
|
||||||
/**
|
|
||||||
* QuickJSDeferredPromise wraps a QuickJS promise [[handle]] and allows
|
|
||||||
* [[resolve]]ing or [[reject]]ing that promise. Use it to bridge asynchronous
|
|
||||||
* code on the host to APIs inside a QuickJSContext.
|
|
||||||
*
|
|
||||||
* Managing the lifetime of promises is tricky. There are three
|
|
||||||
* [[QuickJSHandle]]s inside of each deferred promise object: (1) the promise
|
|
||||||
* itself, (2) the `resolve` callback, and (3) the `reject` callback.
|
|
||||||
*
|
|
||||||
* - If the promise will be fulfilled before the end of it's [[owner]]'s lifetime,
|
|
||||||
* the only cleanup necessary is `deferred.handle.dispose()`, because
|
|
||||||
* calling [[resolve]] or [[reject]] will dispose of both callbacks automatically.
|
|
||||||
*
|
|
||||||
* - As the return value of a [[VmFunctionImplementation]], return [[handle]],
|
|
||||||
* and ensure that either [[resolve]] or [[reject]] will be called. No other
|
|
||||||
* clean-up is necessary.
|
|
||||||
*
|
|
||||||
* - In other cases, call [[dispose]], which will dispose [[handle]] as well as the
|
|
||||||
* QuickJS handles that back [[resolve]] and [[reject]]. For this object,
|
|
||||||
* [[dispose]] is idempotent.
|
|
||||||
*/
|
|
||||||
class QuickJSDeferredPromise {
|
|
||||||
/**
|
|
||||||
* Use [[QuickJSContext.newPromise]] to create a new promise instead of calling
|
|
||||||
* this constructor directly.
|
|
||||||
* @unstable
|
|
||||||
*/
|
|
||||||
constructor(args) {
|
|
||||||
/**
|
|
||||||
* Resolve [[handle]] with the given value, if any.
|
|
||||||
* Calling this method after calling [[dispose]] is a no-op.
|
|
||||||
*
|
|
||||||
* Note that after resolving a promise, you may need to call
|
|
||||||
* [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's
|
|
||||||
* callbacks.
|
|
||||||
*/
|
|
||||||
this.resolve = (value) => {
|
|
||||||
if (!this.resolveHandle.alive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.context
|
|
||||||
.unwrapResult(this.context.callFunction(this.resolveHandle, this.context.undefined, value || this.context.undefined))
|
|
||||||
.dispose();
|
|
||||||
this.disposeResolvers();
|
|
||||||
this.onSettled();
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Reject [[handle]] with the given value, if any.
|
|
||||||
* Calling this method after calling [[dispose]] is a no-op.
|
|
||||||
*
|
|
||||||
* Note that after rejecting a promise, you may need to call
|
|
||||||
* [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's
|
|
||||||
* callbacks.
|
|
||||||
*/
|
|
||||||
this.reject = (value) => {
|
|
||||||
if (!this.rejectHandle.alive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.context
|
|
||||||
.unwrapResult(this.context.callFunction(this.rejectHandle, this.context.undefined, value || this.context.undefined))
|
|
||||||
.dispose();
|
|
||||||
this.disposeResolvers();
|
|
||||||
this.onSettled();
|
|
||||||
};
|
|
||||||
this.dispose = () => {
|
|
||||||
if (this.handle.alive) {
|
|
||||||
this.handle.dispose();
|
|
||||||
}
|
|
||||||
this.disposeResolvers();
|
|
||||||
};
|
|
||||||
this.context = args.context;
|
|
||||||
this.owner = args.context.runtime;
|
|
||||||
this.handle = args.promiseHandle;
|
|
||||||
this.settled = new Promise((resolve) => {
|
|
||||||
this.onSettled = resolve;
|
|
||||||
});
|
|
||||||
this.resolveHandle = args.resolveHandle;
|
|
||||||
this.rejectHandle = args.rejectHandle;
|
|
||||||
}
|
|
||||||
get alive() {
|
|
||||||
return this.handle.alive || this.resolveHandle.alive || this.rejectHandle.alive;
|
|
||||||
}
|
|
||||||
disposeResolvers() {
|
|
||||||
if (this.resolveHandle.alive) {
|
|
||||||
this.resolveHandle.dispose();
|
|
||||||
}
|
|
||||||
if (this.rejectHandle.alive) {
|
|
||||||
this.rejectHandle.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSDeferredPromise = QuickJSDeferredPromise;
|
|
||||||
//# sourceMappingURL=deferred-promise.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,97 +0,0 @@
|
|||||||
import { BorrowedHeapCharPointer, JSContextPointer, JSRuntimePointer, JSValueConstPointer, JSValuePointer, OwnedHeapCharPointer } from "./types-ffi";
|
|
||||||
declare namespace Emscripten {
|
|
||||||
interface FileSystemType {
|
|
||||||
}
|
|
||||||
type EnvironmentType = "WEB" | "NODE" | "SHELL" | "WORKER";
|
|
||||||
type ValueType = "number" | "string" | "array" | "boolean";
|
|
||||||
type TypeCompatibleWithC = number | string | any[] | boolean;
|
|
||||||
type WebAssemblyImports = Array<{
|
|
||||||
name: string;
|
|
||||||
kind: string;
|
|
||||||
}>;
|
|
||||||
type WebAssemblyExports = Array<{
|
|
||||||
module: string;
|
|
||||||
name: string;
|
|
||||||
kind: string;
|
|
||||||
}>;
|
|
||||||
interface CCallOpts {
|
|
||||||
async?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Typings for the features we use to interface with our Emscripten build of
|
|
||||||
* QuickJS.
|
|
||||||
*/
|
|
||||||
interface EmscriptenModule {
|
|
||||||
/**
|
|
||||||
* Write JS `str` to HeapChar pointer.
|
|
||||||
* https://emscripten.org/docs/api_reference/preamble.js.html#stringToUTF8
|
|
||||||
*/
|
|
||||||
stringToUTF8(str: string, outPtr: OwnedHeapCharPointer, maxBytesToRead?: number): void;
|
|
||||||
/**
|
|
||||||
* HeapChar to JS string.
|
|
||||||
* https://emscripten.org/docs/api_reference/preamble.js.html#UTF8ToString
|
|
||||||
*/
|
|
||||||
UTF8ToString(ptr: BorrowedHeapCharPointer, maxBytesToRead?: number): string;
|
|
||||||
lengthBytesUTF8(str: string): number;
|
|
||||||
_malloc(size: number): number;
|
|
||||||
_free(ptr: number): void;
|
|
||||||
cwrap(ident: string, returnType: Emscripten.ValueType | null, argTypes: Emscripten.ValueType[], opts?: Emscripten.CCallOpts): (...args: any[]) => any;
|
|
||||||
HEAP8: Int8Array;
|
|
||||||
HEAP16: Int16Array;
|
|
||||||
HEAP32: Int32Array;
|
|
||||||
HEAPU8: Uint8Array;
|
|
||||||
HEAPU16: Uint16Array;
|
|
||||||
HEAPU32: Uint32Array;
|
|
||||||
HEAPF32: Float32Array;
|
|
||||||
HEAPF64: Float64Array;
|
|
||||||
TOTAL_STACK: number;
|
|
||||||
TOTAL_MEMORY: number;
|
|
||||||
FAST_MEMORY: number;
|
|
||||||
}
|
|
||||||
declare const AsyncifySleepReturnValue: unique symbol;
|
|
||||||
/** @private */
|
|
||||||
export type AsyncifySleepResult<T> = T & typeof AsyncifySleepReturnValue;
|
|
||||||
/**
|
|
||||||
* Allows us to optionally suspend the Emscripten runtime to wait for a promise.
|
|
||||||
* https://emscripten.org/docs/porting/asyncify.html#ways-to-use-async-apis-in-older-engines
|
|
||||||
* ```
|
|
||||||
* EM_JS(int, do_fetch, (), {
|
|
||||||
* return Asyncify.handleSleep(function (wakeUp) {
|
|
||||||
* out("waiting for a fetch");
|
|
||||||
* fetch("a.html").then(function (response) {
|
|
||||||
* out("got the fetch response");
|
|
||||||
* // (normally you would do something with the fetch here)
|
|
||||||
* wakeUp(42);
|
|
||||||
* });
|
|
||||||
* });
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export interface Asyncify {
|
|
||||||
handleSleep<T>(maybeAsyncFn: (wakeUp: (result: T) => void) => void): AsyncifySleepResult<T>;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export interface EmscriptenModuleCallbacks {
|
|
||||||
callFunction: (asyncify: Asyncify | undefined, ctx: JSContextPointer, this_ptr: JSValueConstPointer, argc: number, argv: JSValueConstPointer, fn_id: number) => JSValuePointer | AsyncifySleepResult<JSValuePointer>;
|
|
||||||
loadModuleSource: (asyncify: Asyncify | undefined, rt: JSRuntimePointer, ctx: JSContextPointer, module_name: string) => BorrowedHeapCharPointer | AsyncifySleepResult<BorrowedHeapCharPointer>;
|
|
||||||
normalizeModule: (asyncify: Asyncify | undefined, rt: JSRuntimePointer, ctx: JSContextPointer, module_base_name: string, module_name: string) => BorrowedHeapCharPointer | AsyncifySleepResult<BorrowedHeapCharPointer>;
|
|
||||||
shouldInterrupt: (asyncify: Asyncify | undefined, rt: JSRuntimePointer) => 0 | 1 | AsyncifySleepResult<0 | 1>;
|
|
||||||
}
|
|
||||||
export interface QuickJSEmscriptenModule extends EmscriptenModule {
|
|
||||||
type: "sync";
|
|
||||||
callbacks: EmscriptenModuleCallbacks;
|
|
||||||
}
|
|
||||||
export interface QuickJSAsyncEmscriptenModule extends EmscriptenModule {
|
|
||||||
/** @todo Implement this field */
|
|
||||||
type: "async";
|
|
||||||
callbacks: EmscriptenModuleCallbacks;
|
|
||||||
}
|
|
||||||
export type EitherModule = QuickJSEmscriptenModule | QuickJSAsyncEmscriptenModule;
|
|
||||||
export interface EmscriptenModuleLoader<T extends EmscriptenModule> {
|
|
||||||
(): Promise<T>;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
// This is a subset of the Emscripten type definitions from @types/emscripten
|
|
||||||
// Project: http://kripken.github.io/emscripten-site/index.html
|
|
||||||
// Definitions by: Kensuke Matsuzaki <https://github.com/zakki>
|
|
||||||
// Periklis Tsirakidis <https://github.com/periklis>
|
|
||||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
||||||
//
|
|
||||||
// quickjs-emscripten doesn't use the full EmscriptenModule type from @types/emscripten because:
|
|
||||||
//
|
|
||||||
// - the upstream types define many properties that don't exist on our module due
|
|
||||||
// to our build settings
|
|
||||||
// - some upstream types reference web-only ambient types like WebGL stuff, which
|
|
||||||
// we don't use.
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//# sourceMappingURL=emscripten-types.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
28
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/errors.d.ts
generated
vendored
28
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/errors.d.ts
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
import type { QuickJSContext } from "./context";
|
|
||||||
/**
|
|
||||||
* Error thrown if [[QuickJSContext.unwrapResult]] unwraps an error value that isn't an object.
|
|
||||||
*/
|
|
||||||
export declare class QuickJSUnwrapError extends Error {
|
|
||||||
cause: unknown;
|
|
||||||
context?: QuickJSContext | undefined;
|
|
||||||
name: string;
|
|
||||||
constructor(cause: unknown, context?: QuickJSContext | undefined);
|
|
||||||
}
|
|
||||||
export declare class QuickJSWrongOwner extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class QuickJSUseAfterFree extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class QuickJSNotImplemented extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class QuickJSAsyncifyError extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class QuickJSAsyncifySuspended extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class QuickJSMemoryLeakDetected extends Error {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
58
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/errors.js
generated
vendored
58
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/errors.js
generated
vendored
@@ -1,58 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.QuickJSMemoryLeakDetected = exports.QuickJSAsyncifySuspended = exports.QuickJSAsyncifyError = exports.QuickJSNotImplemented = exports.QuickJSUseAfterFree = exports.QuickJSWrongOwner = exports.QuickJSUnwrapError = void 0;
|
|
||||||
/**
|
|
||||||
* Error thrown if [[QuickJSContext.unwrapResult]] unwraps an error value that isn't an object.
|
|
||||||
*/
|
|
||||||
class QuickJSUnwrapError extends Error {
|
|
||||||
constructor(cause, context) {
|
|
||||||
super(String(cause));
|
|
||||||
this.cause = cause;
|
|
||||||
this.context = context;
|
|
||||||
this.name = "QuickJSUnwrapError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSUnwrapError = QuickJSUnwrapError;
|
|
||||||
class QuickJSWrongOwner extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSWrongOwner";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSWrongOwner = QuickJSWrongOwner;
|
|
||||||
class QuickJSUseAfterFree extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSUseAfterFree";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSUseAfterFree = QuickJSUseAfterFree;
|
|
||||||
class QuickJSNotImplemented extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSNotImplemented";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSNotImplemented = QuickJSNotImplemented;
|
|
||||||
class QuickJSAsyncifyError extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSAsyncifyError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSAsyncifyError = QuickJSAsyncifyError;
|
|
||||||
class QuickJSAsyncifySuspended extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSAsyncifySuspended";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSAsyncifySuspended = QuickJSAsyncifySuspended;
|
|
||||||
class QuickJSMemoryLeakDetected extends Error {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.name = "QuickJSMemoryLeakDetected";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSMemoryLeakDetected = QuickJSMemoryLeakDetected;
|
|
||||||
//# sourceMappingURL=errors.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../ts/errors.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,MAAa,kBAAmB,SAAQ,KAAK;IAE3C,YAAmB,KAAc,EAAS,OAAwB;QAChE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QADH,UAAK,GAAL,KAAK,CAAS;QAAS,YAAO,GAAP,OAAO,CAAiB;QADlE,SAAI,GAAG,oBAAoB,CAAA;IAG3B,CAAC;CACF;AALD,gDAKC;AAED,MAAa,iBAAkB,SAAQ,KAAK;IAA5C;;QACE,SAAI,GAAG,mBAAmB,CAAA;IAC5B,CAAC;CAAA;AAFD,8CAEC;AAED,MAAa,mBAAoB,SAAQ,KAAK;IAA9C;;QACE,SAAI,GAAG,qBAAqB,CAAA;IAC9B,CAAC;CAAA;AAFD,kDAEC;AAED,MAAa,qBAAsB,SAAQ,KAAK;IAAhD;;QACE,SAAI,GAAG,uBAAuB,CAAA;IAChC,CAAC;CAAA;AAFD,sDAEC;AAED,MAAa,oBAAqB,SAAQ,KAAK;IAA/C;;QACE,SAAI,GAAG,sBAAsB,CAAA;IAC/B,CAAC;CAAA;AAFD,oDAEC;AAED,MAAa,wBAAyB,SAAQ,KAAK;IAAnD;;QACE,SAAI,GAAG,0BAA0B,CAAA;IACnC,CAAC;CAAA;AAFD,4DAEC;AAED,MAAa,yBAA0B,SAAQ,KAAK;IAApD;;QACE,SAAI,GAAG,2BAA2B,CAAA;IACpC,CAAC;CAAA;AAFD,8DAEC","sourcesContent":["import type { QuickJSContext } from \"./context\"\n\n/**\n * Error thrown if [[QuickJSContext.unwrapResult]] unwraps an error value that isn't an object.\n */\nexport class QuickJSUnwrapError extends Error {\n name = \"QuickJSUnwrapError\"\n constructor(public cause: unknown, public context?: QuickJSContext) {\n super(String(cause))\n }\n}\n\nexport class QuickJSWrongOwner extends Error {\n name = \"QuickJSWrongOwner\"\n}\n\nexport class QuickJSUseAfterFree extends Error {\n name = \"QuickJSUseAfterFree\"\n}\n\nexport class QuickJSNotImplemented extends Error {\n name = \"QuickJSNotImplemented\"\n}\n\nexport class QuickJSAsyncifyError extends Error {\n name = \"QuickJSAsyncifyError\"\n}\n\nexport class QuickJSAsyncifySuspended extends Error {\n name = \"QuickJSAsyncifySuspended\"\n}\n\nexport class QuickJSMemoryLeakDetected extends Error {\n name = \"QuickJSMemoryLeakDetected\"\n}\n"]}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/** Typescript thinks import('...js/.d.ts') needs mod.default.default */
|
|
||||||
declare function fakeUnwrapDefault<T>(mod: {
|
|
||||||
default: T;
|
|
||||||
}): T;
|
|
||||||
/** Typescript thinks import('...ts') doesn't need mod.default.default, but does */
|
|
||||||
declare function actualUnwrapDefault<T>(mod: T): T;
|
|
||||||
export declare const unwrapTypescript: typeof actualUnwrapDefault;
|
|
||||||
export declare const unwrapJavascript: typeof fakeUnwrapDefault;
|
|
||||||
export {};
|
|
||||||
19
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/esmHelpers.js
generated
vendored
19
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/esmHelpers.js
generated
vendored
@@ -1,19 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.unwrapJavascript = exports.unwrapTypescript = void 0;
|
|
||||||
/** Typescript thinks import('...js/.d.ts') needs mod.default.default */
|
|
||||||
function fakeUnwrapDefault(mod) {
|
|
||||||
// console.log("fakeUnwrapDefault", mod)
|
|
||||||
return mod.default;
|
|
||||||
}
|
|
||||||
/** Typescript thinks import('...ts') doesn't need mod.default.default, but does */
|
|
||||||
function actualUnwrapDefault(mod) {
|
|
||||||
// console.log("actualUnwrapDefault", mod)
|
|
||||||
const maybeUnwrap = mod.default;
|
|
||||||
return maybeUnwrap ?? mod;
|
|
||||||
}
|
|
||||||
// I'm not sure if this behavior is needed in all runtimes,
|
|
||||||
// or just for mocha + ts-node.
|
|
||||||
exports.unwrapTypescript = actualUnwrapDefault;
|
|
||||||
exports.unwrapJavascript = fakeUnwrapDefault;
|
|
||||||
//# sourceMappingURL=esmHelpers.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"esmHelpers.js","sourceRoot":"","sources":["../ts/esmHelpers.ts"],"names":[],"mappings":";;;AAAA,wEAAwE;AACxE,SAAS,iBAAiB,CAAI,GAAmB;IAC/C,wCAAwC;IACxC,OAAO,GAAG,CAAC,OAAY,CAAA;AACzB,CAAC;AAED,mFAAmF;AACnF,SAAS,mBAAmB,CAAI,GAAM;IACpC,0CAA0C;IAC1C,MAAM,WAAW,GAAI,GAAW,CAAC,OAAO,CAAA;IACxC,OAAO,WAAW,IAAI,GAAG,CAAA;AAC3B,CAAC;AAED,2DAA2D;AAC3D,+BAA+B;AAClB,QAAA,gBAAgB,GAAG,mBAAmB,CAAA;AACtC,QAAA,gBAAgB,GAAG,iBAAiB,CAAA","sourcesContent":["/** Typescript thinks import('...js/.d.ts') needs mod.default.default */\nfunction fakeUnwrapDefault<T>(mod: { default: T }): T {\n // console.log(\"fakeUnwrapDefault\", mod)\n return mod.default as T\n}\n\n/** Typescript thinks import('...ts') doesn't need mod.default.default, but does */\nfunction actualUnwrapDefault<T>(mod: T): T {\n // console.log(\"actualUnwrapDefault\", mod)\n const maybeUnwrap = (mod as any).default\n return maybeUnwrap ?? mod\n}\n\n// I'm not sure if this behavior is needed in all runtimes,\n// or just for mocha + ts-node.\nexport const unwrapTypescript = actualUnwrapDefault\nexport const unwrapJavascript = fakeUnwrapDefault\n"]}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export = QuickJSRaw;
|
|
||||||
declare function QuickJSRaw(QuickJSRaw?: {}): any;
|
|
||||||
declare namespace QuickJSRaw {
|
|
||||||
export { QuickJSRaw };
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,67 +0,0 @@
|
|||||||
import { QuickJSEmscriptenModule } from "../emscripten-types";
|
|
||||||
import { JSRuntimePointer, JSContextPointer, JSContextPointerPointer, JSValuePointer, JSValueConstPointer, JSValuePointerPointer, JSValueConstPointerPointer, BorrowedHeapCharPointer, OwnedHeapCharPointer, JSBorrowedCharPointer, JSVoidPointer, EvalFlags, EvalDetectModule } from "../types-ffi";
|
|
||||||
/**
|
|
||||||
* Low-level FFI bindings to QuickJS's Emscripten module.
|
|
||||||
* See instead [[QuickJSContext]], the public Javascript interface exposed by this
|
|
||||||
* library.
|
|
||||||
*
|
|
||||||
* @unstable The FFI interface is considered private and may change.
|
|
||||||
*/
|
|
||||||
export declare class QuickJSFFI {
|
|
||||||
private module;
|
|
||||||
constructor(module: QuickJSEmscriptenModule);
|
|
||||||
/** Set at compile time. */
|
|
||||||
readonly DEBUG = false;
|
|
||||||
QTS_Throw: (ctx: JSContextPointer, error: JSValuePointer | JSValueConstPointer) => JSValuePointer;
|
|
||||||
QTS_NewError: (ctx: JSContextPointer) => JSValuePointer;
|
|
||||||
QTS_RuntimeSetMemoryLimit: (rt: JSRuntimePointer, limit: number) => void;
|
|
||||||
QTS_RuntimeComputeMemoryUsage: (rt: JSRuntimePointer, ctx: JSContextPointer) => JSValuePointer;
|
|
||||||
QTS_RuntimeDumpMemoryUsage: (rt: JSRuntimePointer) => OwnedHeapCharPointer;
|
|
||||||
QTS_RecoverableLeakCheck: () => number;
|
|
||||||
QTS_BuildIsSanitizeLeak: () => number;
|
|
||||||
QTS_RuntimeSetMaxStackSize: (rt: JSRuntimePointer, stack_size: number) => void;
|
|
||||||
QTS_GetUndefined: () => JSValueConstPointer;
|
|
||||||
QTS_GetNull: () => JSValueConstPointer;
|
|
||||||
QTS_GetFalse: () => JSValueConstPointer;
|
|
||||||
QTS_GetTrue: () => JSValueConstPointer;
|
|
||||||
QTS_NewRuntime: () => JSRuntimePointer;
|
|
||||||
QTS_FreeRuntime: (rt: JSRuntimePointer) => void;
|
|
||||||
QTS_NewContext: (rt: JSRuntimePointer) => JSContextPointer;
|
|
||||||
QTS_FreeContext: (ctx: JSContextPointer) => void;
|
|
||||||
QTS_FreeValuePointer: (ctx: JSContextPointer, value: JSValuePointer) => void;
|
|
||||||
QTS_FreeValuePointerRuntime: (rt: JSRuntimePointer, value: JSValuePointer) => void;
|
|
||||||
QTS_FreeVoidPointer: (ctx: JSContextPointer, ptr: JSVoidPointer) => void;
|
|
||||||
QTS_FreeCString: (ctx: JSContextPointer, str: JSBorrowedCharPointer) => void;
|
|
||||||
QTS_DupValuePointer: (ctx: JSContextPointer, val: JSValuePointer | JSValueConstPointer) => JSValuePointer;
|
|
||||||
QTS_NewObject: (ctx: JSContextPointer) => JSValuePointer;
|
|
||||||
QTS_NewObjectProto: (ctx: JSContextPointer, proto: JSValuePointer | JSValueConstPointer) => JSValuePointer;
|
|
||||||
QTS_NewArray: (ctx: JSContextPointer) => JSValuePointer;
|
|
||||||
QTS_NewFloat64: (ctx: JSContextPointer, num: number) => JSValuePointer;
|
|
||||||
QTS_GetFloat64: (ctx: JSContextPointer, value: JSValuePointer | JSValueConstPointer) => number;
|
|
||||||
QTS_NewString: (ctx: JSContextPointer, string: BorrowedHeapCharPointer) => JSValuePointer;
|
|
||||||
QTS_GetString: (ctx: JSContextPointer, value: JSValuePointer | JSValueConstPointer) => JSBorrowedCharPointer;
|
|
||||||
QTS_NewSymbol: (ctx: JSContextPointer, description: BorrowedHeapCharPointer, isGlobal: number) => JSValuePointer;
|
|
||||||
QTS_GetSymbolDescriptionOrKey: (ctx: JSContextPointer, value: JSValuePointer | JSValueConstPointer) => JSBorrowedCharPointer;
|
|
||||||
QTS_IsGlobalSymbol: (ctx: JSContextPointer, value: JSValuePointer | JSValueConstPointer) => number;
|
|
||||||
QTS_IsJobPending: (rt: JSRuntimePointer) => number;
|
|
||||||
QTS_ExecutePendingJob: (rt: JSRuntimePointer, maxJobsToExecute: number, lastJobContext: JSContextPointerPointer) => JSValuePointer;
|
|
||||||
QTS_GetProp: (ctx: JSContextPointer, this_val: JSValuePointer | JSValueConstPointer, prop_name: JSValuePointer | JSValueConstPointer) => JSValuePointer;
|
|
||||||
QTS_SetProp: (ctx: JSContextPointer, this_val: JSValuePointer | JSValueConstPointer, prop_name: JSValuePointer | JSValueConstPointer, prop_value: JSValuePointer | JSValueConstPointer) => void;
|
|
||||||
QTS_DefineProp: (ctx: JSContextPointer, this_val: JSValuePointer | JSValueConstPointer, prop_name: JSValuePointer | JSValueConstPointer, prop_value: JSValuePointer | JSValueConstPointer, get: JSValuePointer | JSValueConstPointer, set: JSValuePointer | JSValueConstPointer, configurable: boolean, enumerable: boolean, has_value: boolean) => void;
|
|
||||||
QTS_Call: (ctx: JSContextPointer, func_obj: JSValuePointer | JSValueConstPointer, this_obj: JSValuePointer | JSValueConstPointer, argc: number, argv_ptrs: JSValueConstPointerPointer) => JSValuePointer;
|
|
||||||
QTS_ResolveException: (ctx: JSContextPointer, maybe_exception: JSValuePointer) => JSValuePointer;
|
|
||||||
QTS_Dump: (ctx: JSContextPointer, obj: JSValuePointer | JSValueConstPointer) => JSBorrowedCharPointer;
|
|
||||||
QTS_Eval: (ctx: JSContextPointer, js_code: BorrowedHeapCharPointer, filename: string, detectModule: EvalDetectModule, evalFlags: EvalFlags) => JSValuePointer;
|
|
||||||
QTS_Typeof: (ctx: JSContextPointer, value: JSValuePointer | JSValueConstPointer) => OwnedHeapCharPointer;
|
|
||||||
QTS_GetGlobalObject: (ctx: JSContextPointer) => JSValuePointer;
|
|
||||||
QTS_NewPromiseCapability: (ctx: JSContextPointer, resolve_funcs_out: JSValuePointerPointer) => JSValuePointer;
|
|
||||||
QTS_TestStringArg: (string: string) => void;
|
|
||||||
QTS_BuildIsDebug: () => number;
|
|
||||||
QTS_BuildIsAsyncify: () => number;
|
|
||||||
QTS_NewFunction: (ctx: JSContextPointer, func_id: number, name: string) => JSValuePointer;
|
|
||||||
QTS_ArgvGetJSValueConstPointer: (argv: JSValuePointer | JSValueConstPointer, index: number) => JSValueConstPointer;
|
|
||||||
QTS_RuntimeEnableInterruptHandler: (rt: JSRuntimePointer) => void;
|
|
||||||
QTS_RuntimeDisableInterruptHandler: (rt: JSRuntimePointer) => void;
|
|
||||||
QTS_RuntimeEnableModuleLoader: (rt: JSRuntimePointer, use_custom_normalize: number) => void;
|
|
||||||
QTS_RuntimeDisableModuleLoader: (rt: JSRuntimePointer) => void;
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.QuickJSFFI = void 0;
|
|
||||||
/**
|
|
||||||
* Low-level FFI bindings to QuickJS's Emscripten module.
|
|
||||||
* See instead [[QuickJSContext]], the public Javascript interface exposed by this
|
|
||||||
* library.
|
|
||||||
*
|
|
||||||
* @unstable The FFI interface is considered private and may change.
|
|
||||||
*/
|
|
||||||
class QuickJSFFI {
|
|
||||||
constructor(module) {
|
|
||||||
this.module = module;
|
|
||||||
/** Set at compile time. */
|
|
||||||
this.DEBUG = false;
|
|
||||||
this.QTS_Throw = this.module.cwrap("QTS_Throw", "number", ["number", "number"]);
|
|
||||||
this.QTS_NewError = this.module.cwrap("QTS_NewError", "number", ["number"]);
|
|
||||||
this.QTS_RuntimeSetMemoryLimit = this.module.cwrap("QTS_RuntimeSetMemoryLimit", null, ["number", "number"]);
|
|
||||||
this.QTS_RuntimeComputeMemoryUsage = this.module.cwrap("QTS_RuntimeComputeMemoryUsage", "number", ["number", "number"]);
|
|
||||||
this.QTS_RuntimeDumpMemoryUsage = this.module.cwrap("QTS_RuntimeDumpMemoryUsage", "number", ["number"]);
|
|
||||||
this.QTS_RecoverableLeakCheck = this.module.cwrap("QTS_RecoverableLeakCheck", "number", []);
|
|
||||||
this.QTS_BuildIsSanitizeLeak = this.module.cwrap("QTS_BuildIsSanitizeLeak", "number", []);
|
|
||||||
this.QTS_RuntimeSetMaxStackSize = this.module.cwrap("QTS_RuntimeSetMaxStackSize", null, ["number", "number"]);
|
|
||||||
this.QTS_GetUndefined = this.module.cwrap("QTS_GetUndefined", "number", []);
|
|
||||||
this.QTS_GetNull = this.module.cwrap("QTS_GetNull", "number", []);
|
|
||||||
this.QTS_GetFalse = this.module.cwrap("QTS_GetFalse", "number", []);
|
|
||||||
this.QTS_GetTrue = this.module.cwrap("QTS_GetTrue", "number", []);
|
|
||||||
this.QTS_NewRuntime = this.module.cwrap("QTS_NewRuntime", "number", []);
|
|
||||||
this.QTS_FreeRuntime = this.module.cwrap("QTS_FreeRuntime", null, ["number"]);
|
|
||||||
this.QTS_NewContext = this.module.cwrap("QTS_NewContext", "number", ["number"]);
|
|
||||||
this.QTS_FreeContext = this.module.cwrap("QTS_FreeContext", null, ["number"]);
|
|
||||||
this.QTS_FreeValuePointer = this.module.cwrap("QTS_FreeValuePointer", null, ["number", "number"]);
|
|
||||||
this.QTS_FreeValuePointerRuntime = this.module.cwrap("QTS_FreeValuePointerRuntime", null, ["number", "number"]);
|
|
||||||
this.QTS_FreeVoidPointer = this.module.cwrap("QTS_FreeVoidPointer", null, ["number", "number"]);
|
|
||||||
this.QTS_FreeCString = this.module.cwrap("QTS_FreeCString", null, ["number", "number"]);
|
|
||||||
this.QTS_DupValuePointer = this.module.cwrap("QTS_DupValuePointer", "number", ["number", "number"]);
|
|
||||||
this.QTS_NewObject = this.module.cwrap("QTS_NewObject", "number", ["number"]);
|
|
||||||
this.QTS_NewObjectProto = this.module.cwrap("QTS_NewObjectProto", "number", ["number", "number"]);
|
|
||||||
this.QTS_NewArray = this.module.cwrap("QTS_NewArray", "number", ["number"]);
|
|
||||||
this.QTS_NewFloat64 = this.module.cwrap("QTS_NewFloat64", "number", ["number", "number"]);
|
|
||||||
this.QTS_GetFloat64 = this.module.cwrap("QTS_GetFloat64", "number", ["number", "number"]);
|
|
||||||
this.QTS_NewString = this.module.cwrap("QTS_NewString", "number", ["number", "number"]);
|
|
||||||
this.QTS_GetString = this.module.cwrap("QTS_GetString", "number", ["number", "number"]);
|
|
||||||
this.QTS_NewSymbol = this.module.cwrap("QTS_NewSymbol", "number", ["number", "number", "number"]);
|
|
||||||
this.QTS_GetSymbolDescriptionOrKey = this.module.cwrap("QTS_GetSymbolDescriptionOrKey", "number", ["number", "number"]);
|
|
||||||
this.QTS_IsGlobalSymbol = this.module.cwrap("QTS_IsGlobalSymbol", "number", ["number", "number"]);
|
|
||||||
this.QTS_IsJobPending = this.module.cwrap("QTS_IsJobPending", "number", ["number"]);
|
|
||||||
this.QTS_ExecutePendingJob = this.module.cwrap("QTS_ExecutePendingJob", "number", ["number", "number", "number"]);
|
|
||||||
this.QTS_GetProp = this.module.cwrap("QTS_GetProp", "number", ["number", "number", "number"]);
|
|
||||||
this.QTS_SetProp = this.module.cwrap("QTS_SetProp", null, ["number", "number", "number", "number"]);
|
|
||||||
this.QTS_DefineProp = this.module.cwrap("QTS_DefineProp", null, ["number", "number", "number", "number", "number", "number", "boolean", "boolean", "boolean"]);
|
|
||||||
this.QTS_Call = this.module.cwrap("QTS_Call", "number", ["number", "number", "number", "number", "number"]);
|
|
||||||
this.QTS_ResolveException = this.module.cwrap("QTS_ResolveException", "number", ["number", "number"]);
|
|
||||||
this.QTS_Dump = this.module.cwrap("QTS_Dump", "number", ["number", "number"]);
|
|
||||||
this.QTS_Eval = this.module.cwrap("QTS_Eval", "number", ["number", "number", "string", "number", "number"]);
|
|
||||||
this.QTS_Typeof = this.module.cwrap("QTS_Typeof", "number", ["number", "number"]);
|
|
||||||
this.QTS_GetGlobalObject = this.module.cwrap("QTS_GetGlobalObject", "number", ["number"]);
|
|
||||||
this.QTS_NewPromiseCapability = this.module.cwrap("QTS_NewPromiseCapability", "number", ["number", "number"]);
|
|
||||||
this.QTS_TestStringArg = this.module.cwrap("QTS_TestStringArg", null, ["string"]);
|
|
||||||
this.QTS_BuildIsDebug = this.module.cwrap("QTS_BuildIsDebug", "number", []);
|
|
||||||
this.QTS_BuildIsAsyncify = this.module.cwrap("QTS_BuildIsAsyncify", "number", []);
|
|
||||||
this.QTS_NewFunction = this.module.cwrap("QTS_NewFunction", "number", ["number", "number", "string"]);
|
|
||||||
this.QTS_ArgvGetJSValueConstPointer = this.module.cwrap("QTS_ArgvGetJSValueConstPointer", "number", ["number", "number"]);
|
|
||||||
this.QTS_RuntimeEnableInterruptHandler = this.module.cwrap("QTS_RuntimeEnableInterruptHandler", null, ["number"]);
|
|
||||||
this.QTS_RuntimeDisableInterruptHandler = this.module.cwrap("QTS_RuntimeDisableInterruptHandler", null, ["number"]);
|
|
||||||
this.QTS_RuntimeEnableModuleLoader = this.module.cwrap("QTS_RuntimeEnableModuleLoader", null, ["number", "number"]);
|
|
||||||
this.QTS_RuntimeDisableModuleLoader = this.module.cwrap("QTS_RuntimeDisableModuleLoader", null, ["number"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.QuickJSFFI = QuickJSFFI;
|
|
||||||
//# sourceMappingURL=ffi.WASM_RELEASE_SYNC.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
75
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/index.d.ts
generated
vendored
75
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/index.d.ts
generated
vendored
@@ -1,75 +0,0 @@
|
|||||||
import type { QuickJSWASMModule } from "./module";
|
|
||||||
import type { QuickJSRuntime, InterruptHandler } from "./runtime";
|
|
||||||
import type { QuickJSContext } from "./context";
|
|
||||||
export type { QuickJSWASMModule, QuickJSContext, QuickJSRuntime };
|
|
||||||
import type { QuickJSAsyncWASMModule } from "./module-asyncify";
|
|
||||||
import type { QuickJSAsyncRuntime } from "./runtime-asyncify";
|
|
||||||
import type { QuickJSAsyncContext, AsyncFunctionImplementation } from "./context-asyncify";
|
|
||||||
import { AsyncRuntimeOptions, ContextOptions } from "./types";
|
|
||||||
export type { QuickJSAsyncContext, QuickJSAsyncRuntime, QuickJSAsyncWASMModule, AsyncFunctionImplementation, };
|
|
||||||
import { newQuickJSWASMModule, newQuickJSAsyncWASMModule, DEBUG_ASYNC, DEBUG_SYNC, RELEASE_ASYNC, RELEASE_SYNC, SyncBuildVariant, AsyncBuildVariant } from "./variants";
|
|
||||||
export { newQuickJSWASMModule, newQuickJSAsyncWASMModule, DEBUG_ASYNC, DEBUG_SYNC, RELEASE_ASYNC, RELEASE_SYNC, SyncBuildVariant, AsyncBuildVariant, };
|
|
||||||
export * from "./vm-interface";
|
|
||||||
export * from "./lifetime";
|
|
||||||
/** Collects the informative errors this library may throw. */
|
|
||||||
export * as errors from "./errors";
|
|
||||||
export * from "./deferred-promise";
|
|
||||||
export * from "./module-test";
|
|
||||||
export type { StaticJSValue, JSValueConst, JSValue, QuickJSHandle, ContextOptions, ContextEvalOptions, RuntimeOptions, AsyncRuntimeOptions, RuntimeOptionsBase, JSModuleLoader, JSModuleLoadResult, JSModuleLoaderAsync, JSModuleLoadSuccess, JSModuleLoadFailure, JSModuleNormalizer, JSModuleNormalizerAsync, JSModuleNormalizeResult, JSModuleNormalizeFailure, JSModuleNormalizeSuccess, } from "./types";
|
|
||||||
export type { ModuleEvalOptions } from "./module";
|
|
||||||
export type { InterruptHandler, ExecutePendingJobsResult } from "./runtime";
|
|
||||||
export type { QuickJSPropertyKey } from "./context";
|
|
||||||
/**
|
|
||||||
* Get a shared singleton {@link QuickJSWASMModule}. Use this to evaluate code
|
|
||||||
* or create Javascript environments.
|
|
||||||
*
|
|
||||||
* This is the top-level entrypoint for the quickjs-emscripten library.
|
|
||||||
*
|
|
||||||
* If you need strictest possible isolation guarantees, you may create a
|
|
||||||
* separate {@link QuickJSWASMModule} via {@link newQuickJSWASMModule}.
|
|
||||||
*
|
|
||||||
* To work with the asyncified version of this library, see these functions:
|
|
||||||
*
|
|
||||||
* - {@link newAsyncRuntime}.
|
|
||||||
* - {@link newAsyncContext}.
|
|
||||||
* - {@link newQuickJSAsyncWASMModule}.
|
|
||||||
*/
|
|
||||||
export declare function getQuickJS(): Promise<QuickJSWASMModule>;
|
|
||||||
/**
|
|
||||||
* Provides synchronous access to the shared {@link QuickJSWASMModule} instance returned by {@link getQuickJS}, as long as
|
|
||||||
* least once.
|
|
||||||
* @throws If called before `getQuickJS` resolves.
|
|
||||||
*/
|
|
||||||
export declare function getQuickJSSync(): QuickJSWASMModule;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSAsyncRuntime]] in a separate WebAssembly module.
|
|
||||||
*
|
|
||||||
* Each runtime is isolated in a separate WebAssembly module, so that errors in
|
|
||||||
* one runtime cannot contaminate another runtime, and each runtime can execute
|
|
||||||
* an asynchronous action without conflicts.
|
|
||||||
*
|
|
||||||
* Note that there is a hard limit on the number of WebAssembly modules in older
|
|
||||||
* versions of v8:
|
|
||||||
* https://bugs.chromium.org/p/v8/issues/detail?id=12076
|
|
||||||
*/
|
|
||||||
export declare function newAsyncRuntime(options?: AsyncRuntimeOptions): Promise<QuickJSAsyncRuntime>;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSAsyncContext]] (with an associated runtime) in an
|
|
||||||
* separate WebAssembly module.
|
|
||||||
*
|
|
||||||
* Each context is isolated in a separate WebAssembly module, so that errors in
|
|
||||||
* one runtime cannot contaminate another runtime, and each runtime can execute
|
|
||||||
* an asynchronous action without conflicts.
|
|
||||||
*
|
|
||||||
* Note that there is a hard limit on the number of WebAssembly modules in older
|
|
||||||
* versions of v8:
|
|
||||||
* https://bugs.chromium.org/p/v8/issues/detail?id=12076
|
|
||||||
*/
|
|
||||||
export declare function newAsyncContext(options?: ContextOptions): Promise<QuickJSAsyncContext>;
|
|
||||||
/**
|
|
||||||
* Returns an interrupt handler that interrupts Javascript execution after a deadline time.
|
|
||||||
*
|
|
||||||
* @param deadline - Interrupt execution if it's still running after this time.
|
|
||||||
* Number values are compared against `Date.now()`
|
|
||||||
*/
|
|
||||||
export declare function shouldInterruptAfterDeadline(deadline: Date | number): InterruptHandler;
|
|
||||||
128
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/index.js
generated
vendored
128
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/index.js
generated
vendored
@@ -1,128 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
||||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
||||||
};
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.shouldInterruptAfterDeadline = exports.newAsyncContext = exports.newAsyncRuntime = exports.getQuickJSSync = exports.getQuickJS = exports.errors = exports.RELEASE_SYNC = exports.RELEASE_ASYNC = exports.DEBUG_SYNC = exports.DEBUG_ASYNC = exports.newQuickJSAsyncWASMModule = exports.newQuickJSWASMModule = void 0;
|
|
||||||
// Build variants
|
|
||||||
const variants_1 = require("./variants");
|
|
||||||
Object.defineProperty(exports, "newQuickJSWASMModule", { enumerable: true, get: function () { return variants_1.newQuickJSWASMModule; } });
|
|
||||||
Object.defineProperty(exports, "newQuickJSAsyncWASMModule", { enumerable: true, get: function () { return variants_1.newQuickJSAsyncWASMModule; } });
|
|
||||||
Object.defineProperty(exports, "DEBUG_ASYNC", { enumerable: true, get: function () { return variants_1.DEBUG_ASYNC; } });
|
|
||||||
Object.defineProperty(exports, "DEBUG_SYNC", { enumerable: true, get: function () { return variants_1.DEBUG_SYNC; } });
|
|
||||||
Object.defineProperty(exports, "RELEASE_ASYNC", { enumerable: true, get: function () { return variants_1.RELEASE_ASYNC; } });
|
|
||||||
Object.defineProperty(exports, "RELEASE_SYNC", { enumerable: true, get: function () { return variants_1.RELEASE_SYNC; } });
|
|
||||||
// Export helpers
|
|
||||||
__exportStar(require("./vm-interface"), exports);
|
|
||||||
__exportStar(require("./lifetime"), exports);
|
|
||||||
/** Collects the informative errors this library may throw. */
|
|
||||||
exports.errors = __importStar(require("./errors"));
|
|
||||||
__exportStar(require("./deferred-promise"), exports);
|
|
||||||
__exportStar(require("./module-test"), exports);
|
|
||||||
let singleton = undefined;
|
|
||||||
let singletonPromise = undefined;
|
|
||||||
/**
|
|
||||||
* Get a shared singleton {@link QuickJSWASMModule}. Use this to evaluate code
|
|
||||||
* or create Javascript environments.
|
|
||||||
*
|
|
||||||
* This is the top-level entrypoint for the quickjs-emscripten library.
|
|
||||||
*
|
|
||||||
* If you need strictest possible isolation guarantees, you may create a
|
|
||||||
* separate {@link QuickJSWASMModule} via {@link newQuickJSWASMModule}.
|
|
||||||
*
|
|
||||||
* To work with the asyncified version of this library, see these functions:
|
|
||||||
*
|
|
||||||
* - {@link newAsyncRuntime}.
|
|
||||||
* - {@link newAsyncContext}.
|
|
||||||
* - {@link newQuickJSAsyncWASMModule}.
|
|
||||||
*/
|
|
||||||
async function getQuickJS() {
|
|
||||||
singletonPromise ?? (singletonPromise = (0, variants_1.newQuickJSWASMModule)().then((instance) => {
|
|
||||||
singleton = instance;
|
|
||||||
return instance;
|
|
||||||
}));
|
|
||||||
return await singletonPromise;
|
|
||||||
}
|
|
||||||
exports.getQuickJS = getQuickJS;
|
|
||||||
/**
|
|
||||||
* Provides synchronous access to the shared {@link QuickJSWASMModule} instance returned by {@link getQuickJS}, as long as
|
|
||||||
* least once.
|
|
||||||
* @throws If called before `getQuickJS` resolves.
|
|
||||||
*/
|
|
||||||
function getQuickJSSync() {
|
|
||||||
if (!singleton) {
|
|
||||||
throw new Error("QuickJS not initialized. Await getQuickJS() at least once.");
|
|
||||||
}
|
|
||||||
return singleton;
|
|
||||||
}
|
|
||||||
exports.getQuickJSSync = getQuickJSSync;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSAsyncRuntime]] in a separate WebAssembly module.
|
|
||||||
*
|
|
||||||
* Each runtime is isolated in a separate WebAssembly module, so that errors in
|
|
||||||
* one runtime cannot contaminate another runtime, and each runtime can execute
|
|
||||||
* an asynchronous action without conflicts.
|
|
||||||
*
|
|
||||||
* Note that there is a hard limit on the number of WebAssembly modules in older
|
|
||||||
* versions of v8:
|
|
||||||
* https://bugs.chromium.org/p/v8/issues/detail?id=12076
|
|
||||||
*/
|
|
||||||
async function newAsyncRuntime(options) {
|
|
||||||
const module = await (0, variants_1.newQuickJSAsyncWASMModule)();
|
|
||||||
return module.newRuntime(options);
|
|
||||||
}
|
|
||||||
exports.newAsyncRuntime = newAsyncRuntime;
|
|
||||||
/**
|
|
||||||
* Create a new [[QuickJSAsyncContext]] (with an associated runtime) in an
|
|
||||||
* separate WebAssembly module.
|
|
||||||
*
|
|
||||||
* Each context is isolated in a separate WebAssembly module, so that errors in
|
|
||||||
* one runtime cannot contaminate another runtime, and each runtime can execute
|
|
||||||
* an asynchronous action without conflicts.
|
|
||||||
*
|
|
||||||
* Note that there is a hard limit on the number of WebAssembly modules in older
|
|
||||||
* versions of v8:
|
|
||||||
* https://bugs.chromium.org/p/v8/issues/detail?id=12076
|
|
||||||
*/
|
|
||||||
async function newAsyncContext(options) {
|
|
||||||
const module = await (0, variants_1.newQuickJSAsyncWASMModule)();
|
|
||||||
return module.newContext(options);
|
|
||||||
}
|
|
||||||
exports.newAsyncContext = newAsyncContext;
|
|
||||||
/**
|
|
||||||
* Returns an interrupt handler that interrupts Javascript execution after a deadline time.
|
|
||||||
*
|
|
||||||
* @param deadline - Interrupt execution if it's still running after this time.
|
|
||||||
* Number values are compared against `Date.now()`
|
|
||||||
*/
|
|
||||||
function shouldInterruptAfterDeadline(deadline) {
|
|
||||||
const deadlineAsNumber = typeof deadline === "number" ? deadline : deadline.getTime();
|
|
||||||
return function () {
|
|
||||||
return Date.now() > deadlineAsNumber;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
exports.shouldInterruptAfterDeadline = shouldInterruptAfterDeadline;
|
|
||||||
//# sourceMappingURL=index.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
115
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/lifetime.d.ts
generated
vendored
115
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/lifetime.d.ts
generated
vendored
@@ -1,115 +0,0 @@
|
|||||||
import { MaybeAsyncBlock } from "./asyncify-helpers";
|
|
||||||
import type { QuickJSHandle } from "./types";
|
|
||||||
/**
|
|
||||||
* An object that can be disposed.
|
|
||||||
* [[Lifetime]] is the canonical implementation of Disposable.
|
|
||||||
* Use [[Scope]] to manage cleaning up multiple disposables.
|
|
||||||
*/
|
|
||||||
export interface Disposable {
|
|
||||||
/**
|
|
||||||
* Dispose of the underlying resources used by this object.
|
|
||||||
*/
|
|
||||||
dispose(): void;
|
|
||||||
/**
|
|
||||||
* @returns true if the object is alive
|
|
||||||
* @returns false after the object has been [[dispose]]d
|
|
||||||
*/
|
|
||||||
alive: boolean;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* A lifetime prevents access to a value after the lifetime has been
|
|
||||||
* [[dispose]]ed.
|
|
||||||
*
|
|
||||||
* Typically, quickjs-emscripten uses Lifetimes to protect C memory pointers.
|
|
||||||
*/
|
|
||||||
export declare class Lifetime<T, TCopy = never, Owner = never> implements Disposable {
|
|
||||||
protected readonly _value: T;
|
|
||||||
protected readonly copier?: ((value: T | TCopy) => TCopy) | undefined;
|
|
||||||
protected readonly disposer?: ((value: T | TCopy) => void) | undefined;
|
|
||||||
protected readonly _owner?: Owner | undefined;
|
|
||||||
protected _alive: boolean;
|
|
||||||
protected _constructorStack: string | undefined;
|
|
||||||
/**
|
|
||||||
* When the Lifetime is disposed, it will call `disposer(_value)`. Use the
|
|
||||||
* disposer function to implement whatever cleanup needs to happen at the end
|
|
||||||
* of `value`'s lifetime.
|
|
||||||
*
|
|
||||||
* `_owner` is not used or controlled by the lifetime. It's just metadata for
|
|
||||||
* the creator.
|
|
||||||
*/
|
|
||||||
constructor(_value: T, copier?: ((value: T | TCopy) => TCopy) | undefined, disposer?: ((value: T | TCopy) => void) | undefined, _owner?: Owner | undefined);
|
|
||||||
get alive(): boolean;
|
|
||||||
/**
|
|
||||||
* The value this Lifetime protects. You must never retain the value - it
|
|
||||||
* may become invalid, leading to memory errors.
|
|
||||||
*
|
|
||||||
* @throws If the lifetime has been [[dispose]]d already.
|
|
||||||
*/
|
|
||||||
get value(): T;
|
|
||||||
get owner(): Owner | undefined;
|
|
||||||
get dupable(): boolean;
|
|
||||||
/**
|
|
||||||
* Create a new handle pointing to the same [[value]].
|
|
||||||
*/
|
|
||||||
dup(): Lifetime<TCopy, TCopy, Owner>;
|
|
||||||
/**
|
|
||||||
* Call `map` with this lifetime, then dispose the lifetime.
|
|
||||||
* @return the result of `map(this)`.
|
|
||||||
*/
|
|
||||||
consume<O>(map: (lifetime: this) => O): O;
|
|
||||||
consume<O>(map: (lifetime: QuickJSHandle) => O): O;
|
|
||||||
/**
|
|
||||||
* Dispose of [[value]] and perform cleanup.
|
|
||||||
*/
|
|
||||||
dispose(): void;
|
|
||||||
private assertAlive;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* A Lifetime that lives forever. Used for constants.
|
|
||||||
*/
|
|
||||||
export declare class StaticLifetime<T, Owner = never> extends Lifetime<T, T, Owner> {
|
|
||||||
constructor(value: T, owner?: Owner);
|
|
||||||
get dupable(): boolean;
|
|
||||||
dup(): this;
|
|
||||||
dispose(): void;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* A Lifetime that does not own its `value`. A WeakLifetime never calls its
|
|
||||||
* `disposer` function, but can be `dup`ed to produce regular lifetimes that
|
|
||||||
* do.
|
|
||||||
*
|
|
||||||
* Used for function arguments.
|
|
||||||
*/
|
|
||||||
export declare class WeakLifetime<T, TCopy = never, Owner = never> extends Lifetime<T, TCopy, Owner> {
|
|
||||||
constructor(value: T, copier?: (value: T | TCopy) => TCopy, disposer?: (value: TCopy) => void, owner?: Owner);
|
|
||||||
dispose(): void;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Scope helps reduce the burden of manually tracking and disposing of
|
|
||||||
* Lifetimes. See [[withScope]]. and [[withScopeAsync]].
|
|
||||||
*/
|
|
||||||
export declare class Scope implements Disposable {
|
|
||||||
/**
|
|
||||||
* Run `block` with a new Scope instance that will be disposed after the block returns.
|
|
||||||
* Inside `block`, call `scope.manage` on each lifetime you create to have the lifetime
|
|
||||||
* automatically disposed after the block returns.
|
|
||||||
*
|
|
||||||
* @warning Do not use with async functions. Instead, use [[withScopeAsync]].
|
|
||||||
*/
|
|
||||||
static withScope<R>(block: (scope: Scope) => R): R;
|
|
||||||
static withScopeMaybeAsync<Return, This, Yielded>(_this: This, block: MaybeAsyncBlock<Return, This, Yielded, [Scope]>): Return | Promise<Return>;
|
|
||||||
/**
|
|
||||||
* Run `block` with a new Scope instance that will be disposed after the
|
|
||||||
* block's returned promise settles. Inside `block`, call `scope.manage` on each
|
|
||||||
* lifetime you create to have the lifetime automatically disposed after the
|
|
||||||
* block returns.
|
|
||||||
*/
|
|
||||||
static withScopeAsync<R>(block: (scope: Scope) => Promise<R>): Promise<R>;
|
|
||||||
private _disposables;
|
|
||||||
/**
|
|
||||||
* Track `lifetime` so that it is disposed when this scope is disposed.
|
|
||||||
*/
|
|
||||||
manage<T extends Disposable>(lifetime: T): T;
|
|
||||||
get alive(): boolean;
|
|
||||||
dispose(): void;
|
|
||||||
}
|
|
||||||
227
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/lifetime.js
generated
vendored
227
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/lifetime.js
generated
vendored
@@ -1,227 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.Scope = exports.WeakLifetime = exports.StaticLifetime = exports.Lifetime = void 0;
|
|
||||||
const asyncify_helpers_1 = require("./asyncify-helpers");
|
|
||||||
const debug_1 = require("./debug");
|
|
||||||
const errors_1 = require("./errors");
|
|
||||||
/**
|
|
||||||
* A lifetime prevents access to a value after the lifetime has been
|
|
||||||
* [[dispose]]ed.
|
|
||||||
*
|
|
||||||
* Typically, quickjs-emscripten uses Lifetimes to protect C memory pointers.
|
|
||||||
*/
|
|
||||||
class Lifetime {
|
|
||||||
/**
|
|
||||||
* When the Lifetime is disposed, it will call `disposer(_value)`. Use the
|
|
||||||
* disposer function to implement whatever cleanup needs to happen at the end
|
|
||||||
* of `value`'s lifetime.
|
|
||||||
*
|
|
||||||
* `_owner` is not used or controlled by the lifetime. It's just metadata for
|
|
||||||
* the creator.
|
|
||||||
*/
|
|
||||||
constructor(_value, copier, disposer, _owner) {
|
|
||||||
this._value = _value;
|
|
||||||
this.copier = copier;
|
|
||||||
this.disposer = disposer;
|
|
||||||
this._owner = _owner;
|
|
||||||
this._alive = true;
|
|
||||||
this._constructorStack = debug_1.QTS_DEBUG ? new Error("Lifetime constructed").stack : undefined;
|
|
||||||
}
|
|
||||||
get alive() {
|
|
||||||
return this._alive;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* The value this Lifetime protects. You must never retain the value - it
|
|
||||||
* may become invalid, leading to memory errors.
|
|
||||||
*
|
|
||||||
* @throws If the lifetime has been [[dispose]]d already.
|
|
||||||
*/
|
|
||||||
get value() {
|
|
||||||
this.assertAlive();
|
|
||||||
return this._value;
|
|
||||||
}
|
|
||||||
get owner() {
|
|
||||||
return this._owner;
|
|
||||||
}
|
|
||||||
get dupable() {
|
|
||||||
return !!this.copier;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Create a new handle pointing to the same [[value]].
|
|
||||||
*/
|
|
||||||
dup() {
|
|
||||||
this.assertAlive();
|
|
||||||
if (!this.copier) {
|
|
||||||
throw new Error("Non-dupable lifetime");
|
|
||||||
}
|
|
||||||
return new Lifetime(this.copier(this._value), this.copier, this.disposer, this._owner);
|
|
||||||
}
|
|
||||||
consume(map) {
|
|
||||||
this.assertAlive();
|
|
||||||
const result = map(this);
|
|
||||||
this.dispose();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Dispose of [[value]] and perform cleanup.
|
|
||||||
*/
|
|
||||||
dispose() {
|
|
||||||
this.assertAlive();
|
|
||||||
if (this.disposer) {
|
|
||||||
this.disposer(this._value);
|
|
||||||
}
|
|
||||||
this._alive = false;
|
|
||||||
}
|
|
||||||
assertAlive() {
|
|
||||||
if (!this.alive) {
|
|
||||||
if (this._constructorStack) {
|
|
||||||
throw new errors_1.QuickJSUseAfterFree(`Lifetime not alive\n${this._constructorStack}\nLifetime used`);
|
|
||||||
}
|
|
||||||
throw new errors_1.QuickJSUseAfterFree("Lifetime not alive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.Lifetime = Lifetime;
|
|
||||||
/**
|
|
||||||
* A Lifetime that lives forever. Used for constants.
|
|
||||||
*/
|
|
||||||
class StaticLifetime extends Lifetime {
|
|
||||||
constructor(value, owner) {
|
|
||||||
super(value, undefined, undefined, owner);
|
|
||||||
}
|
|
||||||
// Static lifetime doesn't need a copier to be copiable
|
|
||||||
get dupable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Copy returns the same instance.
|
|
||||||
dup() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
// Dispose does nothing.
|
|
||||||
dispose() { }
|
|
||||||
}
|
|
||||||
exports.StaticLifetime = StaticLifetime;
|
|
||||||
/**
|
|
||||||
* A Lifetime that does not own its `value`. A WeakLifetime never calls its
|
|
||||||
* `disposer` function, but can be `dup`ed to produce regular lifetimes that
|
|
||||||
* do.
|
|
||||||
*
|
|
||||||
* Used for function arguments.
|
|
||||||
*/
|
|
||||||
class WeakLifetime extends Lifetime {
|
|
||||||
constructor(value, copier, disposer, owner) {
|
|
||||||
// We don't care if the disposer doesn't support freeing T
|
|
||||||
super(value, copier, disposer, owner);
|
|
||||||
}
|
|
||||||
dispose() {
|
|
||||||
this._alive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.WeakLifetime = WeakLifetime;
|
|
||||||
function scopeFinally(scope, blockError) {
|
|
||||||
// console.log('scopeFinally', scope, blockError)
|
|
||||||
let disposeError;
|
|
||||||
try {
|
|
||||||
scope.dispose();
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
disposeError = error;
|
|
||||||
}
|
|
||||||
if (blockError && disposeError) {
|
|
||||||
Object.assign(blockError, {
|
|
||||||
message: `${blockError.message}\n Then, failed to dispose scope: ${disposeError.message}`,
|
|
||||||
disposeError,
|
|
||||||
});
|
|
||||||
throw blockError;
|
|
||||||
}
|
|
||||||
if (blockError || disposeError) {
|
|
||||||
throw blockError || disposeError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Scope helps reduce the burden of manually tracking and disposing of
|
|
||||||
* Lifetimes. See [[withScope]]. and [[withScopeAsync]].
|
|
||||||
*/
|
|
||||||
class Scope {
|
|
||||||
constructor() {
|
|
||||||
this._disposables = new Lifetime(new Set());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Run `block` with a new Scope instance that will be disposed after the block returns.
|
|
||||||
* Inside `block`, call `scope.manage` on each lifetime you create to have the lifetime
|
|
||||||
* automatically disposed after the block returns.
|
|
||||||
*
|
|
||||||
* @warning Do not use with async functions. Instead, use [[withScopeAsync]].
|
|
||||||
*/
|
|
||||||
static withScope(block) {
|
|
||||||
const scope = new Scope();
|
|
||||||
let blockError;
|
|
||||||
try {
|
|
||||||
return block(scope);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
blockError = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
scopeFinally(scope, blockError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static withScopeMaybeAsync(_this, block) {
|
|
||||||
return (0, asyncify_helpers_1.maybeAsync)(undefined, function* (awaited) {
|
|
||||||
const scope = new Scope();
|
|
||||||
let blockError;
|
|
||||||
try {
|
|
||||||
return yield* awaited.of(block.call(_this, awaited, scope));
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
blockError = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
scopeFinally(scope, blockError);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Run `block` with a new Scope instance that will be disposed after the
|
|
||||||
* block's returned promise settles. Inside `block`, call `scope.manage` on each
|
|
||||||
* lifetime you create to have the lifetime automatically disposed after the
|
|
||||||
* block returns.
|
|
||||||
*/
|
|
||||||
static async withScopeAsync(block) {
|
|
||||||
const scope = new Scope();
|
|
||||||
let blockError;
|
|
||||||
try {
|
|
||||||
return await block(scope);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
blockError = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
scopeFinally(scope, blockError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Track `lifetime` so that it is disposed when this scope is disposed.
|
|
||||||
*/
|
|
||||||
manage(lifetime) {
|
|
||||||
this._disposables.value.add(lifetime);
|
|
||||||
return lifetime;
|
|
||||||
}
|
|
||||||
get alive() {
|
|
||||||
return this._disposables.alive;
|
|
||||||
}
|
|
||||||
dispose() {
|
|
||||||
const lifetimes = Array.from(this._disposables.value.values()).reverse();
|
|
||||||
for (const lifetime of lifetimes) {
|
|
||||||
if (lifetime.alive) {
|
|
||||||
lifetime.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._disposables.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.Scope = Scope;
|
|
||||||
//# sourceMappingURL=lifetime.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
18
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/memory.d.ts
generated
vendored
18
ExACTRegressionScripts/node_modules/@tootallnate/quickjs-emscripten/dist/memory.d.ts
generated
vendored
@@ -1,18 +0,0 @@
|
|||||||
import { EitherModule } from "./emscripten-types";
|
|
||||||
import { OwnedHeapCharPointer, JSContextPointerPointer, JSValueConstPointerPointer, JSValuePointerPointer } from "./types-ffi";
|
|
||||||
import { Lifetime } from "./lifetime";
|
|
||||||
import { QuickJSHandle } from "./types";
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export declare class ModuleMemory {
|
|
||||||
module: EitherModule;
|
|
||||||
constructor(module: EitherModule);
|
|
||||||
toPointerArray(handleArray: QuickJSHandle[]): Lifetime<JSValueConstPointerPointer>;
|
|
||||||
newMutablePointerArray<T extends JSContextPointerPointer | JSValuePointerPointer>(length: number): Lifetime<{
|
|
||||||
typedArray: Int32Array;
|
|
||||||
ptr: T;
|
|
||||||
}>;
|
|
||||||
newHeapCharPointer(string: string): Lifetime<OwnedHeapCharPointer>;
|
|
||||||
consumeHeapCharPointer(ptr: OwnedHeapCharPointer): string;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user