Compare commits

...

43 Commits

Author SHA1 Message Date
Benjamin Eckel
ea1c153af4 fix: Fix the release action 2022-11-29 10:19:31 -06:00
Benjamin Eckel
9e30cd1932 remove generate file 2022-11-28 19:24:45 -06:00
Benjamin Eckel
3dccf9b5cf put back mistake 2022-11-28 19:22:05 -06:00
Benjamin Eckel
af090dbe4d Merge branch 'main' into v0.0.1 2022-11-28 19:21:13 -06:00
Benjamin Eckel
832a644e11 release: Bump to 0.0.1 2022-11-28 19:14:11 -06:00
Steve Manuel
821661d391 fix: resolve php sdk issues (#95) 2022-11-28 18:04:27 -07:00
zach
f28e01125e Updates for wasmtime/wasmtime-wasi/wasmtime-wasi-nn, basic support for calling _start functions (#94)
- Updates codebase to use the latest version of wasmtime, wasmtime-wasi
and wasmtime-wasi-nn
- Allows functions with no return values to be called, this provides
basic support for `_start` functions
- For now `_start` functions called by extism still need to use the
extism input/output functions instead of the command line arguments
2022-11-28 14:08:52 -08:00
dependabot[bot]
c0faa53df5 chore(deps-dev): bump prettier from 2.7.1 to 2.8.0 in /node (#90)
Bumps [prettier](https://github.com/prettier/prettier) from 2.7.1 to
2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/releases">prettier's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<p><a
href="https://github.com/prettier/prettier/compare/2.7.1...2.8.0">diff</a></p>
<p>🔗 <a href="https://prettier.io/blog/2022/11/23/2.8.0.html">Release
note</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0</h1>
<p><a
href="https://github.com/prettier/prettier/compare/2.7.1...2.8.0">diff</a></p>
<p>🔗 <a href="https://prettier.io/blog/2022/11/23/2.8.0.html">Release
Notes</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="dcc0623911"><code>dcc0623</code></a>
Release 2.8.0</li>
<li><a
href="7f7498109b"><code>7f74981</code></a>
Remove version validattion temp</li>
<li><a
href="876c297589"><code>876c297</code></a>
Update changelog for <code>satisfies</code> (<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13879">#13879</a>)</li>
<li><a
href="fd376000e9"><code>fd37600</code></a>
Update <code>@typescript-eslint/typescript-estree</code> to support
<code>satisfies</code> (<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13872">#13872</a>)</li>
<li><a
href="fac87619a4"><code>fac8761</code></a>
Build(deps): Bump minimatch from 3.0.4 to 3.1.2 in /scripts/release (<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13854">#13854</a>)</li>
<li><a
href="68ea881498"><code>68ea881</code></a>
Update typescript to v4.9 (<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13852">#13852</a>)</li>
<li><a
href="5e0b88329e"><code>5e0b883</code></a>
Fix generate truncate comment (backport <a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13437">#13437</a>)
(<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13814">#13814</a>)</li>
<li><a
href="a980caa7db"><code>a980caa</code></a>
Add missing changelog for <a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13016">#13016</a>
(<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13812">#13812</a>)</li>
<li><a
href="520dbcd36e"><code>520dbcd</code></a>
Add changelog for <a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13783">#13783</a>
(<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13811">#13811</a>)</li>
<li><a
href="ae4d85ab3c"><code>ae4d85a</code></a>
Update description of <code>vueIndentScriptAndStyle</code> option (<a
href="https://github-redirect.dependabot.com/prettier/prettier/issues/13781">#13781</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/prettier/prettier/compare/2.7.1...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=prettier&package-manager=npm_and_yarn&previous-version=2.7.1&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-27 19:46:47 -06:00
dependabot[bot]
be7961bbf6 chore(deps-dev): bump ex_doc from 0.29.0 to 0.29.1 in /elixir (#89)
Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.29.0 to
0.29.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/elixir-lang/ex_doc/blob/main/CHANGELOG.md">ex_doc's
changelog</a>.</em></p>
<blockquote>
<h2>v0.29.1 (2022-11-21)</h2>
<ul>
<li>
<p>Enhancements</p>
<ul>
<li>Add optional function annotations</li>
<li>Support media print on stylesheets</li>
<li>Add download ePub link to footer</li>
<li>Support extras for Erlang</li>
<li>Add tooltip to functions on sidebar</li>
<li>Disable spellcheck and autocorrect on search input</li>
</ul>
</li>
<li>
<p>Bug fix</p>
<ul>
<li>Special handle functions called <code>record/*</code> in Erlang</li>
</ul>
</li>
<li>
<p>Deprecations</p>
<ul>
<li>Rename <code>:groups_for_functions</code> to
<code>:groups_for_docs</code></li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1439375934"><code>1439375</code></a>
Release v0.29.1</li>
<li><a
href="e4ae7ce037"><code>e4ae7ce</code></a>
Rename groups_for_functions as groups_for_docs</li>
<li><a
href="b17fcd278a"><code>b17fcd2</code></a>
Add optional function annotations (<a
href="https://github-redirect.dependabot.com/elixir-lang/ex_doc/issues/1627">#1627</a>)</li>
<li><a
href="69a74c029c"><code>69a74c0</code></a>
Firefox H2 print rendering fix (<a
href="https://github-redirect.dependabot.com/elixir-lang/ex_doc/issues/1630">#1630</a>)</li>
<li><a
href="623ac03fea"><code>623ac03</code></a>
mix format</li>
<li><a
href="a9284d50e3"><code>a9284d5</code></a>
Consistenly use <strong>doc</strong> for metadata</li>
<li><a
href="a4ea93cf26"><code>a4ea93c</code></a>
Rename internal nodes for consistency</li>
<li><a
href="5a0aa08550"><code>5a0aa08</code></a>
Simplify handling of empty nodes in module summary</li>
<li><a
href="148ad54a6d"><code>148ad54</code></a>
Use v1.13 formatting rules</li>
<li><a
href="4b05286003"><code>4b05286</code></a>
mix format</li>
<li>Additional commits viewable in <a
href="https://github.com/elixir-lang/ex_doc/compare/v0.29.0...v0.29.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ex_doc&package-manager=hex&previous-version=0.29.0&new-version=0.29.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-27 19:46:38 -06:00
Benjamin Eckel
4af4f7c41a fix(php-sdk): fix the composer file (#88)
Need to include new Context file
2022-11-22 16:51:19 -06:00
Benjamin Eckel
0003246ff7 chore: release browser version rc.13 2022-11-21 16:04:21 -06:00
Benjamin Eckel
886e01b959 Merge branch 'main' of github.com:extism/extism 2022-11-21 16:03:05 -06:00
Benjamin Eckel
b30bcc3601 chore: release browser version rc.11 2022-11-21 16:02:25 -06:00
zach
b57d54e63e feat: add var/config functions, merge ExtismPlugin and ExtismPluginCall (#87)
This also only instantiates the module once and combines `ExtismPlugin`
with `ExtismPluginCall`, I can pull out just the new function
implementations if that's an issue.
2022-11-21 13:34:27 -08:00
dependabot[bot]
ba2516650d chore(deps-dev): bump typedoc from 0.23.20 to 0.23.21 in /node (#86)
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.20 to
0.23.21.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/TypeDoc/releases">typedoc's
releases</a>.</em></p>
<blockquote>
<h2>v0.23.21</h2>
<h3>Features</h3>
<ul>
<li>Added support for a catch-all wildcard in
<code>externalSymbolLinkMappings</code>, <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2102">#2102</a>.</li>
<li>Added support for TypeScript 4.9.</li>
</ul>
<h3>Thanks!</h3>
<ul>
<li><a
href="https://github.com/mistic100"><code>@​mistic100</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md">typedoc's
changelog</a>.</em></p>
<blockquote>
<h2>v0.23.21 (2022-11-14)</h2>
<h3>Features</h3>
<ul>
<li>Added support for a catch-all wildcard in
<code>externalSymbolLinkMappings</code>, <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2102">#2102</a>.</li>
<li>Added support for TypeScript 4.9.</li>
</ul>
<h3>Thanks!</h3>
<ul>
<li><a
href="https://github.com/mistic100"><code>@​mistic100</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8a3e195d38"><code>8a3e195</code></a>
Update changelog for release</li>
<li><a
href="530eab35be"><code>530eab3</code></a>
Bump version to 0.23.21</li>
<li><a
href="893c86c6a8"><code>893c86c</code></a>
Fix lint</li>
<li><a
href="38fe129856"><code>38fe129</code></a>
CI fix?</li>
<li><a
href="9b62e0ce6e"><code>9b62e0c</code></a>
Add support for TS 4.9</li>
<li><a
href="8e190487b1"><code>8e19048</code></a>
Tweak changelog notes</li>
<li><a
href="0ba5af5204"><code>0ba5af5</code></a>
Merge pull request <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2102">#2102</a>
from mistic100/external-wildcard</li>
<li><a
href="4b0a9b0a90"><code>4b0a9b0</code></a>
Fix <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2101">#2101</a>
support externalSymbolLinkMappings wildcard</li>
<li><a
href="1ab233b1cf"><code>1ab233b</code></a>
reg-suit begone! -300 dev dependencies</li>
<li><a
href="ab51894154"><code>ab51894</code></a>
Clean up some unnecessary any</li>
<li>Additional commits viewable in <a
href="https://github.com/TypeStrong/TypeDoc/compare/v0.23.20...v0.23.21">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typedoc&package-manager=npm_and_yarn&previous-version=0.23.20&new-version=0.23.21)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 10:01:14 -06:00
dependabot[bot]
97b4582aa4 chore(deps-dev): bump typescript from 4.8.4 to 4.9.3 in /node (#85)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.8.4
to 4.9.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Microsoft/TypeScript/releases">typescript's
releases</a>.</em></p>
<blockquote>
<h2>TypeScript 4.9</h2>
<p>For release notes, check out the <a
href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/">release
announcement</a>.</p>
<p>Downloads are available on:</p>
<ul>
<li><a href="https://www.npmjs.com/package/typescript">npm</a></li>
<li><a
href="https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild">NuGet
package</a></li>
</ul>
<h2>Changes:</h2>
<ul>
<li>93bd577458d55cd720b2677705feab5c91eb12ce Bump version to 4.9.3 and
LKG.</li>
<li>107f832b80df2dc97748021cb00af2b6813db75b Update LKG.</li>
<li>31bee5682df130a14ffdd5742f994dbe7313dd0e Cherry-pick PR <a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/50977">#50977</a>
into release-4.9 (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51363">#51363</a>)
[ <a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/50872">#50872</a>
]</li>
<li>1e2fa7ae15f8530910fef8b916ec8a4ed0b59c45 Update version to 4.9.2-rc
and LKG.</li>
<li>7ab89e5c6e401d161f31f28a6c555a3ba530910e Merge remote-tracking
branch 'origin/main' into release-4.9</li>
<li>e5cd686defb1a4cbdb36bd012357ba5bed28f371 Update
package-lock.json</li>
<li>8d40dc15d1b9945837e7860320fdccfe27c40cad Update
package-lock.json</li>
<li>5cfb3a2fe344a5350734305193e6cc99516285ca Only call return() for an
abrupt completion in user code (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51297">#51297</a>)</li>
<li>a7a9d158e817fcb0e94dc1c24e0a401b21be0cc9 Fix for broken baseline in
yieldInForInInDownlevelGenerator (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51345">#51345</a>)</li>
<li>7f8426f4df0d0a7dd8b72079dafc3e60164a23b1 fix for-in enumeration
containing yield in generator (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51295">#51295</a>)</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li>3d2b4017eb6b9a2b94bc673291e56ae95e8beddd Fix assertion functions
accessed via wildcard imports (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51324">#51324</a>)</li>
<li>64d0d5ae140b7b26a09e75114517b418d6bcaa9f fix(51301): Fixing an
unused import at the end of a line removes the newline (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51320">#51320</a>)</li>
<li>754eeb2986bde30d5926e0fa99c87dda9266d01b Update CodeQL workflow and
configuration, fix found bugs (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51263">#51263</a>)</li>
<li>d8aad262006ad2d2c91aa7a0e4449b4b83c57f7b Update
package-lock.json</li>
<li>d4f26c840b1db76c0b25a405c8e73830a2b45cbc fix(51245): Class with
parameter decorator in arrow function causes &quot;convert to default
export&quot; refactoring failure (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51256">#51256</a>)</li>
<li>16faf45682173ea437a50330feb4785578923d7f Update
package-lock.json</li>
<li>8b1ecdb701e2a2e19e9f8bcdd6b2beac087eabee fix(50654): &quot;Move to a
new file&quot; breaks the declaration of referenced variable (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/50681">#50681</a>)</li>
<li>170a17fad57eae619c5ef2b7bdb3ac00d6c32c47 Dom update 2022-10-25 (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51300">#51300</a>)</li>
<li>9c4e14d75174432f6a4dc5967a09712a6784ab88 Remove &quot;No type
information for this code&quot; from baseline (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51311">#51311</a>)</li>
<li>88d25b4f232929df59729156dfda6b65277affec fix(50068): Refactors
trigger debug failure when JSX text has a ' and a tag on the same line.
(<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51299">#51299</a>)</li>
<li>8bee69acf410d4986cb0cc102b949e2d133d5380 Update
package-lock.json</li>
<li>702de1eeaaef88a189e4d06e5a2aae287853790a Fix early call to
return/throw on generator (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51294">#51294</a>)</li>
<li>2c12b1499908ad7718e65d20e264561207c22375 Add a GH Action to file a
new issue if we go a week without seeing a typescript-error-deltas issue
(<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51271">#51271</a>)</li>
<li>6af270dee09d62516f6dc02ec102a745ffebc037 Update
package-lock.json</li>
<li>2cc4c16a26672a7ba6c97ba16309fcf334db7cae Update
package-lock.json</li>
<li>60934915d9ccc4ca9c0fb2cd060d7ec81601942b Fix apparent typo in
getStringMappingType (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51248">#51248</a>)</li>
<li>61c26096e3373719ece686b84c698423890e9a5f Update
package-lock.json</li>
<li>ef69116c41cb6805f89e6592eacb0ccb7f02207d Generate shortest
<code>rootDirs</code> module specifier instead of first possible (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51244">#51244</a>)</li>
<li>bbb42f453dc684e03d977c5b70391124d57543a9 Fix typo in
canWatchDirectoryOrFile found by CodeQL (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51262">#51262</a>)</li>
<li>a56b254ad3c52b598bc5d44f83f3d0a1cf806068 Include 'this' type
parameter in isRelatedTo fast path (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51230">#51230</a>)</li>
<li>3abd351c0eea55758f27ee5558a4a1525b77f45b Fix super property
transform in async arrow in method (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51240">#51240</a>)</li>
<li>eed05112180e0d94f78aa02d676d49468f15dc31 Update
package-lock.json</li>
<li>2625c1feae25aede35465ca835440fc57bf13d52 Make the init config
category order predictable (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51247">#51247</a>)</li>
<li>1ca99b34029dafad2c18af7bdc0711f4abf7e522 fix(50551): Destructuring
assignment with var bypasses &quot;variable is used before being
assigned&quot; check (2454) (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/50560">#50560</a>)</li>
<li>3f28fa12dfecb8dfd66ce4684bf26f64e1f092f1 Update
package-lock.json</li>
<li>906ebe49334a3a9c2dbd73cd3c902898bc712b66 Revert
structuredTypeRelatedTo change and fix isUnitLikeType (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51076">#51076</a>)</li>
<li>8ac465239f52de1da3ada8cdc4c3f107f4d62e45 change type (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51231">#51231</a>)</li>
<li>245a02cbed7ad50a21289730159abc8d19a66f40 fix(51222):
Go-to-definition on return statements should jump to the containing
function declaration (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51227">#51227</a>)</li>
<li>2dff34e8c4a91c0005ca9ccfb7e045e225b6f2e4 markAliasReferenced should
include ExportValue as well (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51219">#51219</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="93bd577458"><code>93bd577</code></a>
Bump version to 4.9.3 and LKG.</li>
<li><a
href="107f832b80"><code>107f832</code></a>
Update LKG.</li>
<li><a
href="31bee5682d"><code>31bee56</code></a>
Cherry-pick PR <a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/50977">#50977</a>
into release-4.9 (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51363">#51363</a>)</li>
<li><a
href="1e2fa7ae15"><code>1e2fa7a</code></a>
Update version to 4.9.2-rc and LKG.</li>
<li><a
href="7ab89e5c6e"><code>7ab89e5</code></a>
Merge remote-tracking branch 'origin/main' into release-4.9</li>
<li><a
href="e5cd686def"><code>e5cd686</code></a>
Update package-lock.json</li>
<li><a
href="8d40dc15d1"><code>8d40dc1</code></a>
Update package-lock.json</li>
<li><a
href="5cfb3a2fe3"><code>5cfb3a2</code></a>
Only call return() for an abrupt completion in user code (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51297">#51297</a>)</li>
<li><a
href="a7a9d158e8"><code>a7a9d15</code></a>
Fix for broken baseline in yieldInForInInDownlevelGenerator (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51345">#51345</a>)</li>
<li><a
href="7f8426f4df"><code>7f8426f</code></a>
fix for-in enumeration containing yield in generator (<a
href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/51295">#51295</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/Microsoft/TypeScript/compare/v4.8.4...v4.9.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typescript&package-manager=npm_and_yarn&previous-version=4.8.4&new-version=4.9.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 10:01:03 -06:00
dependabot[bot]
762feb1056 chore(deps-dev): bump jest from 29.2.2 to 29.3.1 in /node (#84)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest)
from 29.2.2 to 29.3.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/jest/releases">jest's
releases</a>.</em></p>
<blockquote>
<h2>v29.3.1</h2>
<h2>Fixes</h2>
<ul>
<li><code>[jest-config]</code> Do not warn about <code>preset</code> in
<code>ProjectConfig</code> <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13583">#13583</a></li>
</ul>
<h2>Performance</h2>
<ul>
<li><code>[jest-transform]</code> Defer creation of cache directory <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13420">#13420</a></li>
</ul>
<h2>v29.3.0</h2>
<h2>Features</h2>
<ul>
<li><code>[jest-runtime]</code> Support WebAssembly (Wasm) imports in
ESM modules (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13505">#13505</a>)</li>
</ul>
<h2>Fixes</h2>
<ul>
<li><code>[jest-config]</code> Add config validation for
<code>projects</code> option (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13565">#13565</a>)</li>
<li><code>[jest-mock]</code> Treat cjs modules as objects so they can be
mocked (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13513">#13513</a>)</li>
<li><code>[jest-worker]</code> Throw an error instead of hanging when
jest workers terminate unexpectedly (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13566">#13566</a>)</li>
</ul>
<h2>Chore &amp; Maintenance</h2>
<ul>
<li><code>[@jest/transform]</code> Update
<code>convert-source-map</code> (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13509">#13509</a>)</li>
<li><code>[docs]</code> Mention <code>toStrictEqual</code> in
UsingMatchers docs. (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13560">#13560</a>)</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Tofandel"><code>@​Tofandel</code></a>
made their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13513">facebook/jest#13513</a></li>
<li><a
href="https://github.com/RyWilliams"><code>@​RyWilliams</code></a> made
their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13520">facebook/jest#13520</a></li>
<li><a href="https://github.com/waikoo"><code>@​waikoo</code></a> made
their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13447">facebook/jest#13447</a></li>
<li><a href="https://github.com/kachkaev"><code>@​kachkaev</code></a>
made their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13505">facebook/jest#13505</a></li>
<li><a href="https://github.com/ibuibu"><code>@​ibuibu</code></a> made
their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13565">facebook/jest#13565</a></li>
<li><a
href="https://github.com/necipallef"><code>@​necipallef</code></a> made
their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13560">facebook/jest#13560</a></li>
<li><a
href="https://github.com/ravshansbox"><code>@​ravshansbox</code></a>
made their first contribution in <a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13533">facebook/jest#13533</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/facebook/jest/compare/v29.2.2...v29.3.0">https://github.com/facebook/jest/compare/v29.2.2...v29.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/jest/blob/main/CHANGELOG.md">jest's
changelog</a>.</em></p>
<blockquote>
<h2>29.3.1</h2>
<h3>Fixes</h3>
<ul>
<li><code>[jest-config]</code> Do not warn about <code>preset</code> in
<code>ProjectConfig</code> (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13583">#13583</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li><code>[jest-transform]</code> Defer creation of cache directory (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13420">#13420</a>)</li>
</ul>
<h2>29.3.0</h2>
<h3>Features</h3>
<ul>
<li><code>[jest-runtime]</code> Support WebAssembly (Wasm) imports in
ESM modules (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13505">#13505</a>)</li>
</ul>
<h3>Fixes</h3>
<ul>
<li><code>[jest-config]</code> Add config validation for
<code>projects</code> option (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13565">#13565</a>)</li>
<li><code>[jest-mock]</code> Treat cjs modules as objects so they can be
mocked (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13513">#13513</a>)</li>
<li><code>[jest-worker]</code> Throw an error instead of hanging when
jest workers terminate unexpectedly (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13566">#13566</a>)</li>
</ul>
<h3>Chore &amp; Maintenance</h3>
<ul>
<li><code>[@jest/transform]</code> Update
<code>convert-source-map</code> (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13509">#13509</a>)</li>
<li><code>[docs]</code> Mention <code>toStrictEqual</code> in
UsingMatchers docs. (<a
href="https://github-redirect.dependabot.com/facebook/jest/pull/13560">#13560</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="05deb8393c"><code>05deb83</code></a>
v29.3.1</li>
<li><a
href="84b8de987b"><code>84b8de9</code></a>
v29.3.0</li>
<li>See full diff in <a
href="https://github.com/facebook/jest/commits/v29.3.1/packages/jest">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jest&package-manager=npm_and_yarn&previous-version=29.2.2&new-version=29.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 10:00:53 -06:00
Benjamin Eckel
6267682266 fix(node-sdk): Properly calculate length of utf-8 inputs (#82)
Properly calculate the length of utf-8 inputs. I'll work on getting
unicode chars into our other tests as well and see if we need to fix any
other SDKs
2022-11-20 13:23:01 -06:00
Benjamin Eckel
b1ca2f398d test: Make sure we have unicode in the SDK tests (#83)
Related to https://github.com/extism/extism/pull/82

Ensures we have unicode inputs in our SDK tests. We should probably get
unicode in the output as well
2022-11-20 13:22:48 -06:00
zach
58ad4ce6e2 feat: add extism_http_status_code to get the status code of the last HTTP request + fixes for clippy (#81)
This is kind of hacky but until we have an established way of encoding
complex types in memory it seems good enough
2022-11-18 11:15:17 -08:00
zach
d0296de9a7 fix: python README path (#80) 2022-11-18 09:02:17 -08:00
zach
4db1303273 cleanup: remove extism_load_u32 and extism_store_u32 (#79) 2022-11-16 10:56:20 -08:00
Benjamin Eckel
28d16f2fa8 fix: Fix the python release workflow (#76) 2022-11-14 16:27:01 -06:00
Benjamin Eckel
e3dd34e59f feat(elixir): use result of set_log_file (#39)
We can merge this after we release `rc.6`
2022-11-14 13:58:29 -06:00
Benjamin Eckel
bb6026976c fix: fix test import syntax in browser runtime (#75) 2022-11-10 16:28:01 -06:00
Benjamin Eckel
33c0f8a4c8 chore: bump browser runtime to rc.10 and refactor (#74) 2022-11-10 15:57:38 -06:00
Benjamin Eckel
b57acde149 test(browser-runtime): Add a simple test and runner (#73) 2022-11-09 12:11:59 -06:00
Benjamin Eckel
7e8031fcdc feat: [Experimental] Extism browser runtime (#70)
Experimental browser runtime. Will allow you to load and run simple
Extism plugins in the browser.

Still a work-in-progress. I've currently implemented just enough to run
the `count_vowels` plugin. To try it out:

```
cd browser
npm install
npm run build
python3 -m http.server
```

Open http://localhost:8000

There is a small playground style app. Set the url, and the function
name. Paste in some input. Hit `Run`. The result of the plugin call
should appear on the right.

<img width="964" alt="Screen Shot 2022-11-05 at 2 01 24 PM"
src="https://user-images.githubusercontent.com/185919/200136657-80e90a77-0b79-4f9d-a5dc-f5e1f340d143.png">

Co-authored-by: zach <zachshipko@gmail.com>
2022-11-09 11:02:27 -06:00
zach
e6499cab72 Make Rust SDK depend directly on extism-runtime (#65) 2022-11-07 12:45:56 -08:00
dependabot[bot]
e44800f7f6 chore(deps-dev): bump typedoc from 0.23.19 to 0.23.20 in /node (#71)
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.19 to
0.23.20.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/TypeDoc/releases">typedoc's
releases</a>.</em></p>
<blockquote>
<h2>v0.23.20</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Fixed comment discovery for <code>@inheritDoc</code> if inheriting
from a function type alias, <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2087">#2087</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md">typedoc's
changelog</a>.</em></p>
<blockquote>
<h2>v0.23.20 (2022-11-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Fixed comment discovery for <code>@inheritDoc</code> if inheriting
from a function type alias, <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2087">#2087</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bfa9dbdf51"><code>bfa9dbd</code></a>
Update changelog for release</li>
<li><a
href="ea185d119a"><code>ea185d1</code></a>
Bump version to 0.23.20</li>
<li><a
href="b0012e577d"><code>b0012e5</code></a>
Doc comment</li>
<li><a
href="30555f1776"><code>30555f1</code></a>
Fix comment discovery for <code>@inheritDoc</code></li>
<li>See full diff in <a
href="https://github.com/TypeStrong/TypeDoc/compare/v0.23.19...v0.23.20">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typedoc&package-manager=npm_and_yarn&previous-version=0.23.19&new-version=0.23.20)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 10:35:17 -06:00
dependabot[bot]
d6b403e112 chore(deps-dev): bump @types/jest from 29.2.1 to 29.2.2 in /node (#72)
Bumps
[@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest)
from 29.2.1 to 29.2.2.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/jest&package-manager=npm_and_yarn&previous-version=29.2.1&new-version=29.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 10:34:55 -06:00
Benjamin Eckel
b45c04c13e ci: Workflow per SDK (#69) 2022-11-04 16:24:48 -05:00
Benjamin Eckel
33dbcafdb9 fix: Fix release workflow to use make (#68) 2022-11-04 15:46:25 -05:00
dependabot[bot]
c441ac703e chore(deps-dev): bump @types/node from 18.11.4 to 18.11.9 in /node (#62)
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 18.11.4 to 18.11.9.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/node&package-manager=npm_and_yarn&previous-version=18.11.4&new-version=18.11.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-04 14:41:43 -06:00
dependabot[bot]
3e3c97499c chore(deps-dev): bump @types/jest from 29.2.0 to 29.2.1 in /node (#63)
Bumps
[@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest)
from 29.2.0 to 29.2.1.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/jest&package-manager=npm_and_yarn&previous-version=29.2.0&new-version=29.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-04 14:41:37 -06:00
dependabot[bot]
d131a344a3 chore(deps-dev): bump typedoc from 0.23.18 to 0.23.19 in /node (#64)
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.23.18 to
0.23.19.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/TypeDoc/releases">typedoc's
releases</a>.</em></p>
<blockquote>
<h2>v0.23.19</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Fixed title link if <code>titleLink</code> option was not specified,
<a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2085">#2085</a>.</li>
</ul>
<h3>Thanks!</h3>
<ul>
<li><a
href="https://github.com/krisztianb"><code>@​krisztianb</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md">typedoc's
changelog</a>.</em></p>
<blockquote>
<h2>v0.23.19 (2022-10-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Fixed title link if <code>titleLink</code> option was not specified,
<a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2085">#2085</a>.</li>
</ul>
<h3>Thanks!</h3>
<ul>
<li><a
href="https://github.com/krisztianb"><code>@​krisztianb</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ef598e7427"><code>ef598e7</code></a>
Update changelog for release</li>
<li><a
href="9240b9262f"><code>9240b92</code></a>
Bump version</li>
<li><a
href="15e200b2c9"><code>15e200b</code></a>
Update changelog</li>
<li><a
href="a3cc365b40"><code>a3cc365</code></a>
Merge pull request <a
href="https://github-redirect.dependabot.com/TypeStrong/TypeDoc/issues/2086">#2086</a>
from krisztianb/bugfix/2085-invalid-title-link</li>
<li><a
href="ff8526c2c2"><code>ff8526c</code></a>
Fix wrong handling of missing/empty titleLink option value</li>
<li>See full diff in <a
href="https://github.com/TypeStrong/TypeDoc/compare/v0.23.18...v0.23.19">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typedoc&package-manager=npm_and_yarn&previous-version=0.23.18&new-version=0.23.19)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-04 14:41:29 -06:00
Benjamin Eckel
71110117e4 feat: Add workflow_dispatch to the release workflow (#33) 2022-11-04 15:18:58 -05:00
Benjamin Eckel
5cfa2a0a5e Bump to version 0.0.1-rc.6 (#67)
Co-authored-by: zach <zach@dylib.so>
2022-11-04 14:48:19 -05:00
Benjamin Eckel
cb87a30fb3 docs: Link to the manifest concept doc (#66)
Co-authored-by: Steve Manuel <steve@dylib.so>
2022-11-04 14:04:10 -05:00
Steve Manuel
b85ee0f24c Update README.md 2022-11-04 11:53:06 -06:00
zach
ffc1a1af41 chore: update deps, add dependabot.yml (#61) 2022-11-02 10:51:42 -07:00
zach
a42a7eac5e organize: rename runtime/src/export.rs -> runtime/src/pdk.rs (#60)
This PR just renames `runtime/src/export.rs` to `runtime/src/pdk.rs` to
match `runtime/src/sdk.rs`
2022-11-01 10:21:26 -07:00
zach
08f5b84cd3 ci: fix ocaml build (#59) 2022-10-28 15:18:44 -07:00
69 changed files with 12601 additions and 1092 deletions

41
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "cargo" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "python"
schedule:
interval: "weekly"
- package-ecosystem: "mix"
directory: "elixir"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "node"
schedule:
interval: "weekly"
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "bundler"
directory: "ruby"
schedule:
interval: "weekly"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -3,8 +3,8 @@ on: [pull_request, workflow_dispatch]
name: CI
env:
RUNTIME_MANIFEST: runtime/Cargo.toml
RUNTIME_CRATE: extism-runtime
LIBEXTISM_CRATE: libextism
RUST_SDK_CRATE: extism
jobs:
@@ -41,7 +41,7 @@ jobs:
- name: Build
if: steps.cache-libextism.outputs.cache-hit != 'true'
shell: bash
run: cargo build --release -p ${{ env.RUNTIME_CRATE }}
run: cargo build --release -p ${{ env.LIBEXTISM_CRATE }}
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
@@ -170,6 +170,7 @@ jobs:
- name: Test Python Host SDK
run: |
cd python
cp ../README.md .
poetry install
poetry run python example.py
poetry run python -m unittest discover
@@ -225,6 +226,12 @@ jobs:
LD_LIBRARY_PATH=/usr/local/lib npm run example
LD_LIBRARY_PATH=/usr/local/lib npm run test
- name: Test Browser Runtime
run: |
cd browser
npm i
npm run test
ocaml:
name: OCaml
needs: lib
@@ -247,10 +254,11 @@ jobs:
uses: actions/cache@v3
with:
path: _build
key: ${{ runner.os }}-ocaml-${{ hashFiles('ocaml/**') }}-${{ hashFiles('dune-project') }}
key: ${{ runner.os }}-ocaml-${{ hashFiles('ocaml/lib/**') }}-${{ hashFiles('ocaml/bin/**') }}-${{ hashFiles('dune-project') }}
- name: Build OCaml Host SDK
if: steps.cache-ocaml.outputs.cache-hit != 'true'
run: |
opam install -y --deps-only .
cd ocaml
LD_LIBRARY_PATH=/usr/local/lib opam exec -- dune build
- name: Test OCaml Host SDK

28
.github/workflows/release-elixir.yaml vendored Normal file
View File

@@ -0,0 +1,28 @@
on:
workflow_dispatch:
name: Release Elixir SDK
jobs:
release-sdks:
name: release-elixir
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Elixir Host SDK
uses: erlef/setup-beam@v1
with:
experimental-otp: true
otp-version: '25.0.4'
elixir-version: '1.14.0'
- name: Publish Elixir Host SDK to hex.pm
env:
HEX_API_KEY: ${{ secrets.HEX_PM_API_TOKEN }}
run: |
cd elixir
cp ../LICENSE .
make publish

30
.github/workflows/release-node.yaml vendored Normal file
View File

@@ -0,0 +1,30 @@
on:
workflow_dispatch:
name: Release Node SDK
jobs:
release-sdks:
name: release-node
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node env
uses: actions/setup-node@v3
with:
node-version: 16
registry-url: "https://registry.npmjs.org"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
CI: true
- name: Release Node Host SDK
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
CI: true
run: |
cd node
make publish

37
.github/workflows/release-python.yaml vendored Normal file
View File

@@ -0,0 +1,37 @@
on:
workflow_dispatch:
name: Release Python SDK
jobs:
release-sdks:
name: release-python
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python env
uses: actions/setup-python@v4
with:
python-version: "3.9"
check-latest: true
- name: Run image
uses: abatilo/actions-poetry@v2
- name: Build Python Host SDK
run: |
cd python
cp ../LICENSE .
cp ../README.md .
make clean
make prepare
poetry build
- name: Release Python Host SDK
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: ${{ secrets.PYPI_API_USER }}
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: python/dist/

25
.github/workflows/release-ruby.yaml vendored Normal file
View File

@@ -0,0 +1,25 @@
on:
workflow_dispatch:
name: Release Ruby SDK
jobs:
release-sdks:
name: release-ruby
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Ruby
uses: actions/setup-ruby@v1
with:
ruby-version: '3.1' # Version range or exact version of a Ruby version to use, using semvers version range syntax.
- name: Publish Ruby Gem
env:
RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_TOKEN }}
run: |
cd ruby
make publish

35
.github/workflows/release-rust.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
on:
workflow_dispatch:
name: Release Rust SDK
jobs:
release-sdks:
name: release-rust
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Rust env
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
target: ${{ matrix.target }}
- name: Release Rust Host SDK
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_API_TOKEN }}
run: |
# order of crate publication matter: manifest, runtime, rust
cargo publish --manifest-path manifest/Cargo.toml
# allow for crates.io to update so dependant crates can locate extism-manifest
sleep 5
cargo publish --manifest-path runtime/Cargo.toml --no-verify
cargo publish --manifest-path rust/Cargo.toml

View File

@@ -1,12 +1,13 @@
on:
release:
types: [created]
workflow_dispatch:
name: Release
env:
RUNTIME_MANIFEST: runtime/Cargo.toml
RUNTIME_CRATE: extism-runtime
RUNTIME_CRATE: libextism
RUSTFLAGS: -C target-feature=-crt-static
ARTIFACT_DIR: release-artifacts
@@ -213,112 +214,3 @@ jobs:
files: |
*.tar.gz
*.txt
release-sdks:
needs: [release-linux, release-macos] # release-windows
name: publish-sdks
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node env
uses: actions/setup-node@v3
with:
node-version: 16
registry-url: "https://registry.npmjs.org"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
CI: true
- name: Release Node Host SDK
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
CI: true
run: |
cd node
npm publish
- name: Setup Rust env
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
target: ${{ matrix.target }}
- name: Release Rust Host SDK
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_API_TOKEN }}
run: |
# order of crate publication matter: manifest, runtime, rust
cargo publish --manifest-path manifest/Cargo.toml
# allow for crates.io to update so dependant crates can locate extism-manifest
sleep 5
cargo publish --manifest-path runtime/Cargo.toml --no-verify
cargo publish --manifest-path rust/Cargo.toml
- name: Setup Elixir Host SDK
uses: erlef/setup-beam@v1
with:
experimental-otp: true
otp-version: '25.0.4'
elixir-version: '1.14.0'
- name: Publish Elixir Host SDK to hex.pm
env:
HEX_API_KEY: ${{ secrets.HEX_PM_API_TOKEN }}
run: |
cd elixir
cp ../LICENSE .
mix do deps.get, deps.compile
mix hex.build
mix hex.publish --yes
- name: Setup Ruby
uses: actions/setup-ruby@v1
with:
ruby-version: '3.1' # Version range or exact version of a Ruby version to use, using semvers version range syntax.
- name: Publish Ruby Gem
env:
RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_TOKEN }}
run: |
cd ruby
gem build extism.gemspec
gem push extism*.gem -k $RUBYGEMS_API_KEY
- name: Publish Elixir Host SDK to hex.pm
env:
HEX_API_KEY: ${{ secrets.HEX_PM_API_TOKEN }}
run: |
cd elixir
mix do deps.get, deps.compile
mix hex.build
mix hex.publish --yes
- name: Setup Python env
uses: actions/setup-python@v4
with:
python-version: "3.9"
check-latest: true
- name: Build Python Host SDK
run: |
pushd python
python3 -m pip install --upgrade build
cp ../LICENSE .
cp ../README.md .
python3 -m poetry build
popd
- name: Release Python Host SDK
uses: pypa/gh-action-pypi-publish@release/v1
env:
INPUT_VERIFY_METADATA: false
with:
user: ${{ secrets.PYPI_API_USER }}
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: python/dist/

View File

@@ -3,8 +3,8 @@ members = [
"manifest",
"runtime",
"rust",
"libextism"
]
exclude = [
"elixir/native/extism_nif"
]

View File

@@ -25,7 +25,7 @@ lint:
cargo clippy --release --no-deps --manifest-path runtime/Cargo.toml
build:
cargo build --release $(FEATURE_FLAGS) --manifest-path runtime/Cargo.toml
cargo build --release $(FEATURE_FLAGS) --manifest-path libextism/Cargo.toml
install:
install runtime/extism.h $(DEST)/include

View File

@@ -15,9 +15,11 @@ The universal plug-in system. Run WebAssembly extensions inside your app. Use id
Plug-in development kits (PDK) for plug-in authors supported in [Rust](https://github.com/extism/rust-pdk), [AssemblyScript](https://github.com/extism/assemblyscript-pdk), [Go](https://github.com/extism/go-pdk), [C/C++](https://github.com/extism/c-pdk).
<p align="center">
<img style="width: 70%;" src="https://user-images.githubusercontent.com/7517515/198499438-f3de06e5-71b4-439d-ab31-a3672acc6ede.png"/>
<img style="width: 70%;" src="https://user-images.githubusercontent.com/7517515/200043015-ddfe5833-0252-43a8-bc9e-5b3f829c37d1.png" alt="Extism embedded SDK language support"/>
</p>
Add a flexible, secure, and _bLaZiNg FaSt_ plug-in system to your project. Server, desktop, mobile, web, database -- you name it. Enable users to write and execute safe extensions to your software in **3 easy steps:**
### 1. Import

130
browser/.gitignore vendored Normal file
View File

@@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

5
browser/.prettierrc Normal file
View File

@@ -0,0 +1,5 @@
{
"printWidth": 120,
"trailingComma": "all",
"singleQuote": true
}

23
browser/build.js Normal file
View File

@@ -0,0 +1,23 @@
const { build } = require("esbuild");
const { dependencies, peerDependencies } = require('./package.json')
const sharedConfig = {
entryPoints: ["src/index.ts"],
bundle: true,
minify: false,
drop: [], // preseve debugger statements
external: Object.keys(dependencies || {}).concat(Object.keys(peerDependencies || {})),
};
build({
...sharedConfig,
platform: 'node', // for CJS
outfile: "dist/index.js",
});
build({
...sharedConfig,
outfile: "dist/index.esm.js",
platform: 'neutral', // for ESM
format: "esm",
});

BIN
browser/data/code.wasm Executable file

Binary file not shown.

238
browser/index.html Normal file
View File

@@ -0,0 +1,238 @@
<html>
<head>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<style>
#main {
width: 100%;
}
.manifest {
display: flex; /* or inline-flex */
flex-direction: row;
flex-wrap: nowrap;
width: 100%;
}
.urlInput {
width: 600px;
}
.funcName {
width: 150px;
}
.textAreas {
display: flex; /* or inline-flex */
flex-direction: row;
flex-wrap: nowrap;
width: 100%;
height: 300px;
}
.inputBox {
width: 100%;
height: 100%;
}
.inputBox > textarea {
width: 100%;
height: 100%;
}
.outputBox {
width: 100%;
height: 100%;
}
.outputBox > textarea {
width: 100%;
height: 100%;
}
.space {
height: 80px;
}
.dragAreas {
display: flex; /* or inline-flex */
flex-direction: row;
flex-wrap: nowrap;
width: 100%;
height: 200px;
}
.dragInput {
width: 100%;
height: 100%;
border-style: dotted;
border-color: #000;
}
.dragOutput {
width: 100%;
height: 100%;
}
.dropZone {
width: 100%;
height: 100%;
}
.outputImage {
width: 100%;
height: 100%;
}
</style>
<script type="text/babel">
function getBase64(file, cb) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
cb(reader.result)
};
reader.onerror = function (error) {
console.log("error")
};
}
function arrayTob64(buffer) {
var binary = '';
var bytes = [].slice.call(buffer);
bytes.forEach((b) => binary += String.fromCharCode(b));
return window.btoa(binary);
}
class App extends React.Component {
state = {
url: "https://raw.githubusercontent.com/extism/extism/main/wasm/code.wasm",
input: new Uint8Array(),
output: new Uint8Array(),
func_name: "count_vowels",
functions: []
}
async loadFunctions(url) {
let plugin = await this.extismContext.newPlugin({ "wasm": [ { "path": url } ] })
let functions = await plugin.getExportedFunctions()
console.log("funcs ", functions)
this.setState({functions})
}
componentDidMount() {
this.loadFunctions(this.state.url)
}
constructor(props) {
super(props)
this.extismContext = props.extismContext
}
handleInputChange(e) {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value })
if (e.target.name === "url") {
this.loadFunctions(e.target.value)
}
}
onInputKeyPress(e) {
if (e.keyCode == 13 && e.shiftKey == true) {
e.preventDefault()
this.handleOnRun()
}
}
async handleOnRun(e) {
e && e.preventDefault && e.preventDefault();
let plugin = await this.extismContext.newPlugin({ "wasm": [ { "path": this.state.url } ] })
let result = await plugin.call(this.state.func_name, this.state.input)
let output = result
this.setState({output})
}
nop = (e) => {
e.preventDefault();
e.stopPropagation();
};
handleDrop = e => {
e.preventDefault();
e.stopPropagation();
let files = [...e.dataTransfer.files];
if (files && files.length == 1) {
let file = files[0]
console.log(file)
file.arrayBuffer().then(b => {
this.setState({input: new Uint8Array(b)})
this.handleOnRun()
})
} else {
throw Error("Only one file please")
}
};
render() {
const funcOptions = this.state.functions.map(f => <option value={f}>{f}</option>)
let image = null
if (this.state.output) {
image = <img src={`data:image/png;base64,${arrayTob64(this.state.output)}`}/>
}
return <div className="app">
<div className="manifest">
<div>
<label>WASM Url: </label>
<input type="text" name="url" className="urlInput" value={this.state.url} onChange={this.handleInputChange.bind(this)} />
</div>
<div>
<label>Function: </label>
<select type="text" name="func_name" className="funcName" value={this.state.func_name} onChange={this.handleInputChange.bind(this)}>
{funcOptions}
</select>
</div>
<div>
<button onClick={this.handleOnRun.bind(this)}>Run</button>
</div>
</div>
<div className="textAreas">
<div className="inputBox">
<h3>Text Input</h3>
<textarea name="input" value={this.state.input} onChange={this.handleInputChange.bind(this)} onKeyDown={this.onInputKeyPress.bind(this)}></textarea>
</div>
<div className="outputBox">
<h3>Text Output</h3>
<textarea name="output" value={new TextDecoder().decode(this.state.output)} ></textarea>
</div>
</div>
<div className="space" />
<div className="dragAreas">
<div className="dragInput">
<h3>Image Input</h3>
<div className="dropZone"
onDrop={this.handleDrop.bind(this)}
onDragOver={this.nop.bind(this)}
onDragEnter={this.nop.bind(this)}
onDragLeave={this.nop.bind(this)}
>
</div>
</div>
<div className="dragOutput">
<h3>Image Output</h3>
<div className="outputImage">
{image}
</div>
</div>
</div>
</div>
}
}
window.App = App
</script>
<script type="module">
import {ExtismContext} from './dist/index.esm.js'
const e = React.createElement;
window.onload = () => {
const domContainer = document.getElementById('main');
console.log(domContainer)
const root = ReactDOM.createRoot(domContainer);
const extismContext = new ExtismContext()
root.render(e(App, {extismContext}));
}
</script>
</head>
<body>
<div id="main"></div>
</body>
</html>

5
browser/jest.config.js Normal file
View File

@@ -0,0 +1,5 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

10569
browser/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
browser/package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "@extism/runtime-browser",
"version": "0.0.1",
"description": "Extism runtime in the browser",
"scripts": {
"build": "node build.js && tsc --emitDeclarationOnly --outDir dist",
"format": "prettier --write \"src/**/*.ts\"",
"lint": "tslint -p tsconfig.json",
"test": "jest --config jest.config.js"
},
"private": false,
"publishConfig": {
"access": "public"
},
"files": [
"dist/*"
],
"module": "dist/index.esm.js",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"author": "The Extism Authors <oss@extism.org>",
"license": "BSD-3-Clause",
"devDependencies": {
"@types/jest": "^29.2.2",
"esbuild": "^0.15.13",
"jest": "^29.2.2",
"prettier": "^2.7.1",
"ts-jest": "^29.0.3",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"typedoc": "^0.23.20",
"typescript": "^4.8.4"
}
}

104
browser/src/allocator.ts Normal file
View File

@@ -0,0 +1,104 @@
type MemoryBlock = { offset: bigint; length: bigint };
export default class Allocator {
currentIndex: bigint;
active: Record<number, MemoryBlock>;
freed: MemoryBlock[];
memory: Uint8Array;
constructor(n: number) {
this.currentIndex = BigInt(1);
this.active = {};
this.freed = [];
this.memory = new Uint8Array(n);
}
reset() {
this.currentIndex = BigInt(1);
this.active = {};
this.freed = [];
}
alloc(length: bigint): bigint {
for (var i = 0; i < this.freed.length; i++) {
let block = this.freed[i];
if (block.length === length) {
this.active[Number(block.offset)] = block;
this.freed.splice(i, 1);
return block.offset;
} else if (block.length > length + BigInt(64)) {
const newBlock = { offset: block.offset, length };
block.offset += length;
block.length -= length;
return newBlock.offset;
}
}
// Resize memory if needed
// TODO: put a limit on the memory size
if (BigInt(this.memory.length) < this.currentIndex + length) {
const tmp = new Uint8Array(Number(this.currentIndex + length + BigInt(64)));
tmp.set(this.memory);
this.memory = tmp;
}
const offset = this.currentIndex;
this.currentIndex += length;
this.active[Number(offset)] = { offset, length };
return offset;
}
getBytes(offset: bigint): Uint8Array | null {
const block = this.active[Number(offset)];
if (!block) {
return null;
}
return new Uint8Array(this.memory.buffer, Number(offset), Number(block.length));
}
getString(offset: bigint): string | null {
const bytes = this.getBytes(offset);
if (bytes === null) {
return null;
}
return new TextDecoder().decode(bytes);
}
allocBytes(data: Uint8Array): bigint {
const offs = this.alloc(BigInt(data.length));
const bytes = this.getBytes(offs);
if (bytes === null) {
this.free(offs);
return BigInt(0);
}
bytes.set(data);
return offs;
}
allocString(data: string): bigint {
const bytes = new TextEncoder().encode(data);
return this.allocBytes(bytes);
}
getLength(offset: bigint): bigint {
const block = this.active[Number(offset)];
if (!block) {
return BigInt(0);
}
return block.length;
}
free(offset: bigint) {
const block = this.active[Number(offset)];
if (!block) {
return;
}
delete this.active[Number(offset)];
this.freed.push(block);
}
}

45
browser/src/context.ts Normal file
View File

@@ -0,0 +1,45 @@
import { Manifest, PluginConfig, ManifestWasmFile, ManifestWasmData } from './manifest';
import ExtismPlugin from './plugin';
/**
* Can be a {@link Manifest} or just the raw bytes of the WASM module as an ArrayBuffer.
* We recommend using {@link Manifest}
*/
type ManifestData = Manifest | ArrayBuffer;
/**
* A Context is needed to create plugins. The Context
* is where your plugins live. Freeing the context
* frees all of the plugins in its scope.
*/
export default class ExtismContext {
/**
* Create a plugin managed by this context
*
* @param manifest - The {@link ManifestData} describing the plugin code and config
* @param config - Config details for the plugin
* @returns A new Plugin scoped to this Context
*/
async newPlugin(manifest: ManifestData, config?: PluginConfig) {
let moduleData: ArrayBuffer | null = null;
if (manifest instanceof ArrayBuffer) {
moduleData = manifest;
} else if ((manifest as Manifest).wasm) {
const wasmData = (manifest as Manifest).wasm;
if (wasmData.length > 1) throw Error('This runtime only supports one module in Manifest.wasm');
const wasm = wasmData[0];
if ((wasm as ManifestWasmData).data) {
moduleData = (wasm as ManifestWasmData).data;
} else if ((wasm as ManifestWasmFile).path) {
const response = await fetch((wasm as ManifestWasmFile).path);
moduleData = await response.arrayBuffer();
console.dir(moduleData);
}
}
if (!moduleData) {
throw Error(`Unsure how to interpret manifest ${manifest}`);
}
return new ExtismPlugin(moduleData, config);
}
}

23
browser/src/index.test.ts Normal file
View File

@@ -0,0 +1,23 @@
import { ExtismContext } from './';
import fs from 'fs';
import path from 'path';
function parse(bytes: Uint8Array): any {
return JSON.parse(new TextDecoder().decode(bytes));
}
describe('', () => {
it('can load and call a plugin', async () => {
const data = fs.readFileSync(path.join(__dirname, '..', 'data', 'code.wasm'));
const ctx = new ExtismContext();
const plugin = await ctx.newPlugin({ wasm: [{ data: data }] });
const functions = await plugin.getExports();
expect(Object.keys(functions).filter(x => !x.startsWith("__") && x !== "memory")).toEqual(['count_vowels']);
let output = await plugin.call('count_vowels', 'this is a test');
expect(parse(output)).toEqual({ count: 4 });
output = await plugin.call('count_vowels', 'this is a test again');
expect(parse(output)).toEqual({ count: 7 });
output = await plugin.call('count_vowels', 'this is a test thrice');
expect(parse(output)).toEqual({ count: 6 });
});
});

3
browser/src/index.ts Normal file
View File

@@ -0,0 +1,3 @@
import ExtismContext from './context';
export { ExtismContext };

40
browser/src/manifest.ts Normal file
View File

@@ -0,0 +1,40 @@
/**
* Represents a path or url to a WASM module
*/
export type ManifestWasmFile = {
path: string;
name?: string;
hash?: string;
};
/**
* Represents the raw bytes of a WASM file loaded into memory
*/
export type ManifestWasmData = {
data: Uint8Array;
name?: string;
hash?: string;
};
/**
* {@link ExtismPlugin} Config
*/
export type PluginConfig = Map<string, string>;
/**
* The WASM to load as bytes or a path
*/
export type ManifestWasm = ManifestWasmFile | ManifestWasmData;
/**
* The manifest which describes the {@link ExtismPlugin} code and
* runtime constraints.
*
* @see [Extism > Concepts > Manifest](https://extism.org/docs/concepts/manifest)
*/
export type Manifest = {
wasm: Array<ManifestWasm>;
//memory?: ManifestMemory;
config?: PluginConfig;
allowed_hosts?: Array<string>;
};

170
browser/src/plugin.ts Normal file
View File

@@ -0,0 +1,170 @@
import Allocator from './allocator';
import { PluginConfig } from './manifest';
export default class ExtismPlugin {
moduleData: ArrayBuffer;
allocator: Allocator;
config?: PluginConfig;
vars: Record<string, Uint8Array>;
input: Uint8Array;
output: Uint8Array;
module?: WebAssembly.WebAssemblyInstantiatedSource;
constructor(moduleData: ArrayBuffer, config?: PluginConfig) {
this.moduleData = moduleData;
this.allocator = new Allocator(1024 * 1024);
this.config = config;
this.vars = {};
this.input = new Uint8Array();
this.output = new Uint8Array();
}
async getExports(): Promise<WebAssembly.Exports> {
const module = await this._instantiateModule();
return module.instance.exports;
}
async getImports(): Promise<WebAssembly.ModuleImportDescriptor[]> {
const module = await this._instantiateModule();
return WebAssembly.Module.imports(module.module);
}
async getInstance(): Promise<WebAssembly.Instance> {
const module = await this._instantiateModule();
return module.instance;
}
async call(func_name: string, input: Uint8Array | string): Promise<Uint8Array> {
const module = await this._instantiateModule();
if (typeof input === 'string') {
this.input = new TextEncoder().encode(input);
} else if (input instanceof Uint8Array) {
this.input = input;
} else {
throw new Error('input should be string or Uint8Array');
}
this.allocator.reset();
let func = module.instance.exports[func_name];
if (!func) {
throw Error(`function does not exist ${func_name}`);
}
//@ts-ignore
func();
return this.output;
}
async _instantiateModule(): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
if (this.module) {
return this.module;
}
const environment = this.makeEnv();
this.module = await WebAssembly.instantiate(this.moduleData, { env: environment });
return this.module;
}
makeEnv(): any {
const plugin = this;
return {
extism_alloc(n: bigint): bigint {
return plugin.allocator.alloc(n);
},
extism_free(n: bigint) {
plugin.allocator.free(n);
},
extism_load_u8(n: bigint): number {
return plugin.allocator.memory[Number(n)];
},
extism_load_u64(n: bigint): bigint {
let cast = new DataView(plugin.allocator.memory.buffer, Number(n));
return cast.getBigUint64(0, true);
},
extism_store_u8(offset: bigint, n: number) {
plugin.allocator.memory[Number(offset)] = Number(n);
},
extism_store_u64(offset: bigint, n: bigint) {
const tmp = new DataView(plugin.allocator.memory.buffer, Number(offset));
tmp.setBigUint64(0, n, true);
},
extism_input_length(): bigint {
return BigInt(plugin.input.length);
},
extism_input_load_u8(i: bigint): number {
return plugin.input[Number(i)];
},
extism_input_load_u64(idx: bigint): bigint {
let cast = new DataView(plugin.input.buffer, Number(idx));
return cast.getBigUint64(0, true);
},
extism_output_set(offset: bigint, length: bigint) {
const offs = Number(offset);
const len = Number(length);
plugin.output = plugin.allocator.memory.slice(offs, offs + len);
},
extism_error_set(i: bigint) {
throw plugin.allocator.getString(i);
},
extism_config_get(i: bigint): bigint {
if (typeof plugin.config === 'undefined') {
return BigInt(0);
}
const key = plugin.allocator.getString(i);
if (key === null) {
return BigInt(0);
}
const value = plugin.config.get(key);
if (typeof value === 'undefined') {
return BigInt(0);
}
return plugin.allocator.allocString(value);
},
extism_var_get(i: bigint): bigint {
const key = plugin.allocator.getString(i);
if (key === null) {
return BigInt(0);
}
const value = plugin.vars[key];
if (typeof value === 'undefined') {
return BigInt(0);
}
return plugin.allocator.allocBytes(value);
},
extism_var_set(n: bigint, i: bigint) {
const key = plugin.allocator.getString(n);
if (key === null) {
return;
}
const value = plugin.allocator.getBytes(i);
if (value === null) {
return;
}
plugin.vars[key] = value;
},
extism_http_request(n: bigint, i: bigint): number {
debugger;
return 0;
},
extism_length(i: bigint): bigint {
return plugin.allocator.getLength(i);
},
extism_log_warn(i: bigint) {
const s = plugin.allocator.getString(i);
console.warn(s);
},
extism_log_info(i: bigint) {
const s = plugin.allocator.getString(i);
console.log(s);
},
extism_log_debug(i: bigint) {
const s = plugin.allocator.getString(i);
console.debug(s);
},
extism_log_error(i: bigint) {
const s = plugin.allocator.getString(i);
console.error(s);
},
};
}
}

12
browser/tsconfig.json Normal file
View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"strict": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}

6
browser/tslint.json Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": [
"tslint:recommended",
"tslint-config-prettier"
]
}

View File

@@ -1,50 +1,50 @@
{
"name": "extism/extism",
"description": "Make your software programmable. Run WebAssembly extensions in your app using the first off-the-shelf, universal plug-in system.",
"license": "BSD-3-Clause",
"type": "library",
"keywords": [
"WebAssembly",
"plugin-system",
"runtime",
"plug-in"
],
"authors": [
{
"name": "The Extism Authors",
"email": "oss@extism.org",
"homepage": "https://extism.org"
},
{
"name": "Dylibso, Inc.",
"email": "oss@dylib.so",
"homepage": "https://dylib.so"
}
],
"require": {
"php": "^7.4 || ^8",
"ircmaxell/ffime": "dev-master"
"name": "extism/extism",
"description": "Make your software programmable. Run WebAssembly extensions in your app using the first off-the-shelf, universal plug-in system.",
"license": "BSD-3-Clause",
"type": "library",
"keywords": [
"WebAssembly",
"plugin-system",
"runtime",
"plug-in"
],
"authors": [
{
"name": "The Extism Authors",
"email": "oss@extism.org",
"homepage": "https://extism.org"
},
"suggest": {},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Extism\\": "php/src/"
},
"files": [
"php/src/Plugin.php",
"php/src/generate.php",
"php/src/extism.h"
]
{
"name": "Dylibso, Inc.",
"email": "oss@dylib.so",
"homepage": "https://dylib.so"
}
],
"require": {
"php": "^7.4 || ^8",
"ircmaxell/ffime": "dev-master"
},
"suggest": {},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Extism\\": "php/src/"
},
"autoload-dev": {
"psr-4": {}
},
"config": {
"sort-packages": true
},
"extra": {},
"scripts": {},
"scripts-descriptions": {}
"files": [
"php/src/Context.php",
"php/src/Plugin.php",
"php/src/extism.h"
]
},
"autoload-dev": {
"psr-4": {}
},
"config": {
"sort-packages": true
},
"extra": {},
"scripts": {},
"scripts-descriptions": {}
}

View File

@@ -13,7 +13,7 @@ You can find this package on [hex.pm](https://hex.pm/packages/extism).
```elixir
def deps do
[
{:extism, "~> 0.0.1-rc.5"}
{:extism, "~> 0.0.1-rc.6"}
]
end
```

View File

@@ -49,7 +49,7 @@ defmodule Extism.Context do
## Parameters
- ctx: The Context to manage this plugin
- manifest: The String or Map of the WASM module or manifest
- manifest: The String or Map of the WASM module or [manifest](https://extism.org/docs/concepts/manifest)
- wasi: A bool you set to true if you want WASI support
"""

View File

@@ -44,6 +44,14 @@ defmodule Extism.Plugin do
@doc """
Updates the manifest of the given plugin
## Parameters
- ctx: The Context to manage this plugin
- manifest: The String or Map of the WASM module or [manifest](https://extism.org/docs/concepts/manifest)
- wasi: A bool you set to true if you want WASI support
"""
def update(plugin, manifest, wasi) when is_map(manifest) do
{:ok, manifest_payload} = JSON.encode(manifest)

View File

@@ -4,7 +4,7 @@ defmodule Extism.MixProject do
def project do
[
app: :extism,
version: "0.0.1-rc.5",
version: "0.0.1",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps(),

View File

@@ -1,6 +1,6 @@
%{
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
"ex_doc": {:hex, :ex_doc, "0.29.0", "4a1cb903ce746aceef9c1f9ae8a6c12b742a5461e6959b9d3b24d813ffbea146", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "f096adb8bbca677d35d278223361c7792d496b3fc0d0224c9d4bc2f651af5db1"},
"ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"json": {:hex, :json, "1.4.1", "8648f04a9439765ad449bc56a3ff7d8b11dd44ff08ffcdefc4329f7c93843dfa", [:mix], [], "hexpm", "9abf218dbe4ea4fcb875e087d5f904ef263d012ee5ed21d46e9dbca63f053d16"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},

View File

@@ -1,6 +1,6 @@
[package]
name = "extism_nif"
version = "0.0.1-rc.5"
version = "0.0.1-rc.6"
edition = "2021"
authors = ["Benjamin Eckel <bhelx@simst.im>"]
@@ -11,5 +11,5 @@ crate-type = ["cdylib"]
[dependencies]
rustler = "0.26.0"
extism = { version = "0.0.1-rc.5" }
extism = { version = "0.0.1-rc.6" }
log = "0.4"

View File

@@ -115,8 +115,11 @@ fn set_log_file(filename: String, log_level: String) -> Result<Atom, rustler::Er
match log::Level::from_str(&log_level) {
Err(_e) => Err(rustler::Error::Term(Box::new(format!("{} not a valid log level", log_level)))),
Ok(level) => {
extism::set_log_file(path, Some(level));
Ok(atoms::ok())
if extism::set_log_file(path, Some(level)) {
Ok(atoms::ok())
} else {
Err(rustler::Error::Term(Box::new("Did not set log file, received false from the API.")))
}
}
}
}

View File

@@ -35,6 +35,8 @@ defmodule ExtismTest do
assert JSON.decode(output) == {:ok, %{"count" => 7}}
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "this is a test thrice")
assert JSON.decode(output) == {:ok, %{"count" => 6}}
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "🌎hello🌎world🌎")
assert JSON.decode(output) == {:ok, %{"count" => 3}}
Extism.Context.free(ctx)
end

View File

@@ -194,7 +194,7 @@ func (plugin Plugin) SetConfig(data map[string][]byte) error {
return nil
}
/// FunctionExists returns true when the name function is present in the plugin
// FunctionExists returns true when the named function is present in the plugin
func (plugin Plugin) FunctionExists(functionName string) bool {
name := C.CString(functionName)
b := C.extism_plugin_function_exists(plugin.ctx.pointer, C.int(plugin.id), name)
@@ -202,7 +202,7 @@ func (plugin Plugin) FunctionExists(functionName string) bool {
return bool(b)
}
/// Call a function by name with the given input, returning the output
// Call a function by name with the given input, returning the output
func (plugin Plugin) Call(functionName string, input []byte) ([]byte, error) {
ptr := makePointer(input)
name := C.CString(functionName)

View File

@@ -1,6 +1,6 @@
cabal-version: 2.4
name: extism
version: 0.0.1.0
version: 0.0.1
-- A short (one-line) description of the package.
synopsis: Extism bindings

23
libextism/Cargo.toml Normal file
View File

@@ -0,0 +1,23 @@
[package]
name = "libextism"
version = "0.0.1"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"
homepage = "https://extism.org"
repository = "https://github.com/extism/extism"
description = "libextism"
[lib]
name = "extism"
crate-type = ["cdylib"]
[dependencies]
extism-runtime = {path = "../runtime"}
[features]
default = ["http", "register-http", "register-filesystem"]
nn = ["extism-runtime/nn"]
register-http = ["extism-runtime/register-http"] # enables wasm to be downloaded using http
register-filesystem = ["extism-runtime/register-filesystem"] # enables wasm to be loaded from disk
http = ["extism-runtime/http"] # enables extism_http_request

10
libextism/src/lib.rs Normal file
View File

@@ -0,0 +1,10 @@
//! This crate is used to generate `libextism` using `extism-runtime`
pub use extism_runtime::sdk::*;
#[cfg(test)]
#[test]
fn test_version() {
let s = unsafe { std::ffi::CStr::from_ptr(extism_version()) };
assert!(s.to_bytes() != b"0.0.0");
}

View File

@@ -1,6 +1,6 @@
[package]
name = "extism-manifest"
version = "0.0.1-rc.5"
version = "0.0.1"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"
@@ -9,7 +9,7 @@ repository = "https://github.com/extism/extism"
description = "Extism plug-in manifest crate"
[dependencies]
serde = {version = "1", features=["derive"]}
serde = {version = "1", features = ["derive"]}
base64 = "0.20.0-alpha"
schemars = {version = "0.8", optional=true}

1182
node/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@extism/extism",
"version": "0.0.1-rc.5",
"version": "0.0.1",
"description": "Extism Host SDK for Node",
"keywords": [
"extism",
@@ -36,7 +36,7 @@
"@types/jest": "^29.2.0",
"@types/node": "^18.11.4",
"jest": "^29.2.2",
"prettier": "2.7.1",
"prettier": "2.8.0",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typedoc": "^0.23.18",

View File

@@ -161,6 +161,8 @@ export type ManifestWasm = ManifestWasmFile | ManifestWasmData;
/**
* The manifest which describes the {@link Plugin} code and
* runtime constraints.
*
* @see [Extism > Concepts > Manifest](https://extism.org/docs/concepts/manifest)
*/
export type Manifest = {
wasm: Array<ManifestWasm>;
@@ -216,7 +218,7 @@ export class Context {
/**
* Create a plugin managed by this context
*
* @param manifest - The Manifest describing the plugin code and config
* @param manifest - The {@link Manifest} describing the plugin code and config
* @param wasi - Set to `true` to enable WASI
* @param config - Config details for the plugin
* @returns A new Plugin scoped to this Context
@@ -275,7 +277,7 @@ export class Plugin {
* Constructor for a plugin. @see {@link Context#plugin}.
*
* @param ctx - The context to manage this plugin
* @param manifest - The manifest
* @param manifest - The {@link Manifest}
* @param wasi - Set to true to enable WASI support
* @param config - The plugin config
*/
@@ -297,7 +299,7 @@ export class Plugin {
let plugin = lib.extism_plugin_new(
ctx.pointer,
dataRaw,
dataRaw.length,
Buffer.byteLength(dataRaw, 'utf-8'),
wasi
);
if (plugin < 0) {
@@ -317,14 +319,14 @@ export class Plugin {
if (config != null) {
let s = JSON.stringify(config);
lib.extism_plugin_config(ctx.pointer, this.id, s, s.length);
lib.extism_plugin_config(ctx.pointer, this.id, s, Buffer.byteLength(s, 'utf-8'),);
}
}
/**
* Update an existing plugin with new WASM or manifest
*
* @param manifest - The new manifest data
* @param manifest - The new {@link Manifest} data
* @param wasi - Set to true to enable WASI support
* @param config - The new plugin config
*/
@@ -342,7 +344,7 @@ export class Plugin {
this.ctx.pointer,
this.id,
dataRaw,
dataRaw.length,
Buffer.byteLength(dataRaw, 'utf-8'),
wasi
);
if (!ok) {
@@ -355,7 +357,7 @@ export class Plugin {
if (config != null) {
let s = JSON.stringify(config);
lib.extism_plugin_config(this.ctx.pointer, this.id, s, s.length);
lib.extism_plugin_config(this.ctx.pointer, this.id, s, Buffer.byteLength(s, 'utf-8'),);
}
}
@@ -399,7 +401,7 @@ export class Plugin {
this.id,
functionName,
input.toString(),
input.length
Buffer.byteLength(input, 'utf-8'),
);
if (rc !== 0) {
var err = lib.extism_error(this.ctx.pointer, this.id);

View File

@@ -31,6 +31,9 @@ describe("test extism", () => {
output = await plugin.call("count_vowels", "this is a test thrice");
result = JSON.parse(output.toString());
expect(result["count"]).toBe(6);
output = await plugin.call("count_vowels", "🌎hello🌎world🌎");
result = JSON.parse(output.toString());
expect(result["count"]).toBe(3);
});
});

View File

@@ -1,22 +1,22 @@
{
"name": "extism/example",
"description": "Example running the Extism PHP Host SDK",
"license": "BSD-3-Clause",
"type": "project",
"authors": [
{
"name": "The Extism Authors",
"email": "oss@extism.org"
}
],
"require": {
"extism/extism": "*"
},
"repositories": [
{
"type": "path",
"url": "../../"
}
],
"minimum-stability": "dev"
"name": "extism/example",
"description": "Example running the Extism PHP Host SDK",
"license": "BSD-3-Clause",
"type": "project",
"authors": [
{
"name": "The Extism Authors",
"email": "oss@extism.org"
}
],
"require": {
"extism/extism": "*"
},
"repositories": [
{
"type": "path",
"url": "../../"
}
],
"minimum-stability": "dev"
}

View File

@@ -8,11 +8,11 @@
"packages": [
{
"name": "extism/extism",
"version": "dev-feat-reuse-plugins",
"version": "dev-php-sdk-fix",
"dist": {
"type": "path",
"url": "../..",
"reference": "9e5f576acff0aa9c8720fdf6d1103b7c1996bf14"
"reference": "6119eae37bcb2e02f7c7b5b203ab9f959819e83d"
},
"require": {
"ircmaxell/ffime": "dev-master",
@@ -22,7 +22,12 @@
"autoload": {
"psr-4": {
"Extism\\": "php/src/"
}
},
"files": [
"php/src/Context.php",
"php/src/Plugin.php",
"php/src/extism.h"
]
},
"autoload-dev": {
"psr-4": []
@@ -59,12 +64,12 @@
"source": {
"type": "git",
"url": "https://github.com/ircmaxell/FFIMe.git",
"reference": "7b9e0bf23adceddd5fde3130d30275a45cfc1867"
"reference": "f6911d7a6a7090a9782a21a946819a2efa9a2ff7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ircmaxell/FFIMe/zipball/7b9e0bf23adceddd5fde3130d30275a45cfc1867",
"reference": "7b9e0bf23adceddd5fde3130d30275a45cfc1867",
"url": "https://api.github.com/repos/ircmaxell/FFIMe/zipball/f6911d7a6a7090a9782a21a946819a2efa9a2ff7",
"reference": "f6911d7a6a7090a9782a21a946819a2efa9a2ff7",
"shasum": ""
},
"require": {
@@ -97,7 +102,7 @@
"issues": "https://github.com/ircmaxell/FFIMe/issues",
"source": "https://github.com/ircmaxell/FFIMe/tree/master"
},
"time": "2022-09-07T19:50:56+00:00"
"time": "2022-09-25T18:13:59+00:00"
},
{
"name": "ircmaxell/php-c-parser",
@@ -105,12 +110,12 @@
"source": {
"type": "git",
"url": "https://github.com/ircmaxell/php-c-parser.git",
"reference": "55e0a4fdf88d6e955d928860e1e107a68492c1cf"
"reference": "fd8f5efefd0fcc6c5119d945694acaa3a6790ada"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ircmaxell/php-c-parser/zipball/55e0a4fdf88d6e955d928860e1e107a68492c1cf",
"reference": "55e0a4fdf88d6e955d928860e1e107a68492c1cf",
"url": "https://api.github.com/repos/ircmaxell/php-c-parser/zipball/fd8f5efefd0fcc6c5119d945694acaa3a6790ada",
"reference": "fd8f5efefd0fcc6c5119d945694acaa3a6790ada",
"shasum": ""
},
"require": {
@@ -146,7 +151,7 @@
"issues": "https://github.com/ircmaxell/php-c-parser/issues",
"source": "https://github.com/ircmaxell/php-c-parser/tree/master"
},
"time": "2022-08-27T17:37:14+00:00"
"time": "2022-09-23T19:39:35+00:00"
},
{
"name": "ircmaxell/php-object-symbolresolver",
@@ -154,12 +159,12 @@
"source": {
"type": "git",
"url": "https://github.com/ircmaxell/php-object-symbolresolver.git",
"reference": "88c918a0f4621ef59dc4a4c21ead7f39bd720337"
"reference": "dfe1b1aa6c15b198bdef50fff8485e98e89f2a09"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ircmaxell/php-object-symbolresolver/zipball/88c918a0f4621ef59dc4a4c21ead7f39bd720337",
"reference": "88c918a0f4621ef59dc4a4c21ead7f39bd720337",
"url": "https://api.github.com/repos/ircmaxell/php-object-symbolresolver/zipball/dfe1b1aa6c15b198bdef50fff8485e98e89f2a09",
"reference": "dfe1b1aa6c15b198bdef50fff8485e98e89f2a09",
"shasum": ""
},
"require": {
@@ -191,7 +196,7 @@
"issues": "https://github.com/ircmaxell/php-object-symbolresolver/issues",
"source": "https://github.com/ircmaxell/php-object-symbolresolver/tree/master"
},
"time": "2022-09-07T19:47:04+00:00"
"time": "2022-09-15T18:21:50+00:00"
}
],
"packages-dev": [],

View File

@@ -3,12 +3,37 @@ declare(strict_types=1);
namespace Extism;
require_once "vendor/autoload.php";
require_once "generate.php";
function generate_extism_lib() {
return (new \FFIMe\FFIMe("libextism.".soext()))
->include("extism.h")
->showWarnings(false)
->codeGen('ExtismLib', __DIR__.'/ExtismLib.php');
}
function soext() {
$platform = php_uname("s");
switch ($platform) {
case "Darwin":
return "dylib";
case "Linux":
return "so";
case "Windows":
return "dll";
default:
throw new \Exception("Extism: unsupported platform ".$platform);
}
}
if (!file_exists(__DIR__."/ExtismLib.php")) {
generate_extism_lib();
}
require_once "ExtismLib.php";
$lib = new \ExtismLib(\ExtismLib::SOFILE);
if ($lib == null) {
throw new Exception("Extism: failed to create new runtime instance");
throw new \Exception("Extism: failed to create new runtime instance");
}
class Context

View File

@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Extism;
require_once "vendor/autoload.php";
require_once "generate.php";
require_once "ExtismLib.php";
class Plugin
@@ -34,13 +32,13 @@ class Plugin
$id = $this->lib->extism_plugin_new($ctx->pointer, $data, count($data), (int)$wasi);
if ($id < 0) {
$err = $this->lib->extism_error($ctx->pointer, -1);
throw new Exception("Extism: unable to load plugin: " . $err);
throw new \Exception("Extism: unable to load plugin: " . $err);
}
$this->id = $id;
$this->context = $ctx;
if ($config != null) {
$cfg = string_to_bytes(json_encode(config));
if ($this->config != null) {
$cfg = string_to_bytes(json_encode($config));
$this->lib->extism_plugin_config($ctx->pointer, $this->id, $cfg, count($cfg));
}
}
@@ -73,14 +71,14 @@ class Plugin
if ($err) {
$msg = $msg . ", error = " . $err;
}
throw new Execption("Extism: call to '".$name."' failed with " . $msg);
throw new \Exception("Extism: call to '".$name."' failed with " . $msg);
}
$length = $this->lib->extism_plugin_output_length($this->context->pointer, $this->id);
$buf = $this->lib->extism_plugin_output_data($this->context->pointer, $this->id);
$ouput = [];
$output = [];
$data = $buf->getData();
for ($i = 0; $i < $length; $i++) {
$output[$i] = $data[$i];
@@ -101,7 +99,7 @@ class Plugin
$ok = $this->lib->extism_plugin_update($this->context->pointer, $this->id, $data, count($data), (int)$wasi);
if (!$ok) {
$err = $this->lib->extism_error($this->context->pointer, -1);
throw new Exception("Extism: unable to update plugin: " . $err);
throw new \Exception("Extism: unable to update plugin: " . $err);
}
if ($config != null) {

View File

@@ -1,29 +0,0 @@
<?php
require_once "vendor/autoload.php";
function generate() {
return (new FFIMe\FFIMe("libextism.".soext()))
->include("extism.h")
->showWarnings(false)
->codeGen('ExtismLib', __DIR__.'/ExtismLib.php');
}
function soext() {
$platform = php_uname("s");
switch ($platform) {
case "Darwin":
return "dylib";
case "Linux":
return "so";
case "Windows":
return "dll";
default:
throw new Exeception("Extism: unsupported platform ".$platform);
}
}
if (!file_exists(__DIR__."/ExtismLib.php")) {
generate();
}

View File

@@ -168,7 +168,7 @@ class Context:
Parameters
----------
manifest : Union[str, bytes, dict]
A manifest dictionary describing the plugin or the raw bytes for a module
A manifest dictionary describing the plugin or the raw bytes for a module. See [Extism > Concepts > Manifest](https://extism.org/docs/concepts/manifest/).
wasi : bool
Set to `True` to enable WASI support
config : dict
@@ -220,7 +220,7 @@ class Plugin:
Parameters
----------
plugin : Union[str, bytes, dict]
A manifest dictionary describing the plugin or the raw bytes for a module
A manifest dictionary describing the plugin or the raw bytes for a module. See [Extism > Concepts > Manifest](https://extism.org/docs/concepts/manifest/).
wasi : bool
Set to `True` to enable WASI support
config : dict

View File

@@ -1,9 +1,10 @@
[tool.poetry]
name = "extism"
version = "0.0.1-rc.5"
description = ""
version = "0.0.1"
description = "Extism Host SDK for python"
authors = ["The Extism Authors <oss@extism.org>"]
license = "BSD-3-Clause"
readme = "../README.md"
[tool.poetry.dependencies]
python = "^3.7"

View File

@@ -20,6 +20,8 @@ class TestExtism(unittest.TestCase):
self.assertEqual(j["count"], 7)
j = json.loads(plugin.call("count_vowels", "this is a test thrice"))
self.assertEqual(j["count"], 6)
j = json.loads(plugin.call("count_vowels", "🌎hello🌎world🌎"))
self.assertEqual(j["count"], 3)
def test_update_plugin_manifest(self):
with extism.Context() as ctx:

View File

@@ -86,7 +86,7 @@ module Extism
# Create a new plugin from a WASM module or JSON encoded manifest
#
# @param wasm [Hash, String] The manifest for the plugin
# @param wasm [Hash, String] The manifest for the plugin. See https://extism.org/docs/concepts/manifest/.
# @param wasi [Boolean] Enable WASI support
# @param config [Hash] The plugin config
# @return [Plugin]
@@ -121,7 +121,7 @@ module Extism
#
# @see Extism::Context#plugin
# @param context [Context] The context to manager this plugin
# @param wasm [Hash, String] The manifest or WASM binary
# @param wasm [Hash, String] The manifest or WASM binary. See https://extism.org/docs/concepts/manifest/.
# @param wasi [Boolean] Enable WASI support
# @param config [Hash] The plugin config
def initialize(context, wasm, wasi = false, config = nil)
@@ -151,7 +151,7 @@ module Extism
# Update a plugin with new WASM module or manifest
#
# @param wasm [Hash, String] The manifest or WASM binary
# @param wasm [Hash, String] The manifest or WASM binary. See https://extism.org/docs/concepts/manifest/.
# @param wasi [Boolean] Enable WASI support
# @param config [Hash] The plugin config
# @return [void]

View File

@@ -1,5 +1,5 @@
# frozen_string_literal: true
module Extism
VERSION = "0.0.1.rc4"
VERSION = "0.0.1"
end

View File

@@ -20,6 +20,8 @@ class TestExtism < Minitest::Test
assert_equal res["count"], 7
res = JSON.parse(plugin.call("count_vowels", "this is a test thrice"))
assert_equal res["count"], 6
res = JSON.parse(plugin.call("count_vowels", "🌎hello🌎world🌎"))
assert_equal res["count"], 3
end
end

View File

@@ -1,6 +1,6 @@
[package]
name = "extism-runtime"
version = "0.0.1-rc.5"
version = "0.0.1"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"
@@ -8,27 +8,21 @@ homepage = "https://extism.org"
repository = "https://github.com/extism/extism"
description = "Extism runtime component"
[lib]
name = "extism"
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmtime = "1.0.0"
wasmtime-wasi = "1.0.0"
wasmtime-wasi-nn = {version = "1.0.1", optional=true}
wasmtime = "3.0.0"
wasmtime-wasi = "3.0.0"
wasmtime-wasi-nn = {version = "3.0.0", optional=true}
anyhow = "1"
serde = { version = "1", features=["derive"] }
toml = "0.5"
serde = {version = "1", features = ["derive"]}
serde_json = "1"
toml = "0.5"
sha2 = "0.10"
log = "0.4"
log4rs = "1.1"
url = "2.3"
url = "2"
glob = "0.3"
ureq = {version = "2.5", optional=true}
extism-manifest = { version = "0.0.1-rc.4", path = "../manifest" }
extism-manifest = { version = "0.0.1-rc.6", path = "../manifest" }
pretty-hex = { version = "0.3" }
[features]

View File

@@ -1,10 +1,6 @@
use std::env;
fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
if let Ok(bindings) = cbindgen::Builder::new()
.with_crate(crate_dir)
.with_crate(".")
.with_language(cbindgen::Language::C)
.with_no_includes()
.with_sys_include("stdint.h")

View File

@@ -29,7 +29,7 @@ impl Context {
/// Get the next valid plugin ID
pub fn next_id(&mut self) -> Result<PluginIndex, Error> {
// Make sure we haven't exhausted all plugin IDs, it reach this it would require the machine
// Make sure we haven't exhausted all plugin IDs, to reach this it would require the machine
// running this code to have a lot of memory - no computer I tested on was able to allocate
// the max number of plugins.
//
@@ -37,7 +37,7 @@ impl Context {
// try to use one of those before returning an error
let exhausted = self.next_id.load(std::sync::atomic::Ordering::SeqCst) == PluginIndex::MAX;
// If there is a significant number of old IDs we can start to re-use them
// If there are a significant number of old IDs we can start to re-use them
if self.reclaimed_ids.len() >= START_REUSING_IDS || exhausted {
if let Some(x) = self.reclaimed_ids.pop_front() {
return Ok(x);
@@ -55,6 +55,32 @@ impl Context {
.fetch_add(1, std::sync::atomic::Ordering::SeqCst))
}
pub fn insert(&mut self, plugin: Plugin) -> PluginIndex {
// Generate a new plugin ID
let id: i32 = match self.next_id() {
Ok(id) => id,
Err(e) => {
error!("Error creating Plugin: {:?}", e);
self.set_error(e);
return -1;
}
};
self.plugins.insert(id, plugin);
id
}
pub fn new_plugin(&mut self, data: impl AsRef<[u8]>, with_wasi: bool) -> PluginIndex {
let plugin = match Plugin::new(data, with_wasi) {
Ok(x) => x,
Err(e) => {
error!("Error creating Plugin: {:?}", e);
self.set_error(e);
return -1;
}
};
self.insert(plugin)
}
/// Set the context error
pub fn set_error(&mut self, e: impl std::fmt::Debug) {
trace!("Set context error: {:?}", e);
@@ -78,9 +104,9 @@ impl Context {
/// Remove a plugin from the context
pub fn remove(&mut self, id: PluginIndex) {
self.plugins.remove(&id);
// Collect old IDs in case we need to re-use them
self.reclaimed_ids.push_back(id);
if self.plugins.remove(&id).is_some() {
// Collect old IDs in case we need to re-use them
self.reclaimed_ids.push_back(id);
}
}
}

View File

@@ -2,9 +2,9 @@ pub use anyhow::Error;
pub(crate) use wasmtime::*;
mod context;
pub(crate) mod export;
pub mod manifest;
mod memory;
pub(crate) mod pdk;
mod plugin;
mod plugin_ref;
pub mod sdk;

View File

@@ -84,30 +84,6 @@ impl PluginMemory {
Ok(self.memory.data(&self.store)[offs])
}
/// Write u32 to memory
pub(crate) fn store_u32(&mut self, offs: usize, data: u32) -> Result<(), Error> {
trace!("store_u32: {data:x} at offset {offs}");
let handle = MemoryBlock {
offset: offs,
length: 4,
};
self.write(handle, data.to_ne_bytes())?;
Ok(())
}
/// Read u32 from memory
pub(crate) fn load_u32(&self, offs: usize) -> Result<u32, Error> {
trace!("load_u32: offset {offs}");
let mut buf = [0; 4];
let handle = MemoryBlock {
offset: offs,
length: 4,
};
self.read(handle, &mut buf)?;
Ok(u32::from_ne_bytes(buf))
}
/// Write u64 to memory
pub(crate) fn store_u64(&mut self, offs: usize, data: u64) -> Result<(), Error> {
trace!("store_u64: {data:x} at offset {offs}");

View File

@@ -7,7 +7,7 @@ macro_rules! args {
($input:expr, $index:expr, $ty:ident) => {
match $input[$index].$ty() {
Some(x) => x,
None => return Err(Trap::new("Invalid input type"))
None => return Err(Error::msg("Invalid input type"))
}
};
($input:expr, $(($index:expr, $ty:ident)),*$(,)?) => {
@@ -24,7 +24,7 @@ pub(crate) fn input_length(
caller: Caller<Internal>,
_input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
output[0] = Val::I64(data.input_length as i64);
Ok(())
@@ -37,7 +37,7 @@ pub(crate) fn input_load_u8(
caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
if data.input.is_null() {
return Ok(());
@@ -53,7 +53,7 @@ pub(crate) fn input_load_u64(
caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
if data.input.is_null() {
return Ok(());
@@ -72,12 +72,10 @@ pub(crate) fn store_u8(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let (offset, byte) = args!(input, (0, i64), (1, i32));
data.memory_mut()
.store_u8(offset as usize, byte as u8)
.map_err(|_| Trap::new("Write error"))?;
data.memory_mut().store_u8(offset as usize, byte as u8)?;
Ok(())
}
@@ -88,51 +86,14 @@ pub(crate) fn load_u8(
caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
let offset = args!(input, 0, i64) as usize;
let byte = data
.memory()
.load_u8(offset)
.map_err(|_| Trap::new("Read error"))?;
let byte = data.memory().load_u8(offset)?;
output[0] = Val::I32(byte as i32);
Ok(())
}
/// Store an unsigned 32 bit integer in memory
/// Params: i64 (offset), i32 (int)
/// Returns: none
pub(crate) fn store_u32(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
let data: &mut Internal = caller.data_mut();
let (offset, b) = args!(input, (0, i64), (1, i32));
data.memory_mut()
.store_u32(offset as usize, b as u32)
.map_err(|_| Trap::new("Write error"))?;
Ok(())
}
/// Load an unsigned 32 bit integer from memory
/// Params: i64 (offset)
/// Returns: i32 (int)
pub(crate) fn load_u32(
caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
let data: &Internal = caller.data();
let offset = args!(input, 0, i64) as usize;
let b = data
.memory()
.load_u32(offset)
.map_err(|_| Trap::new("Read error"))?;
output[0] = Val::I32(b as i32);
Ok(())
}
/// Store an unsigned 64 bit integer in memory
/// Params: i64 (offset), i64 (int)
/// Returns: none
@@ -140,12 +101,10 @@ pub(crate) fn store_u64(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let (offset, b) = args!(input, (0, i64), (1, i64));
data.memory_mut()
.store_u64(offset as usize, b as u64)
.map_err(|_| Trap::new("Write error"))?;
data.memory_mut().store_u64(offset as usize, b as u64)?;
Ok(())
}
@@ -156,13 +115,10 @@ pub(crate) fn load_u64(
caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
let offset = args!(input, 0, i64) as usize;
let byte = data
.memory()
.load_u64(offset)
.map_err(|_| Trap::new("Read error"))?;
let byte = data.memory().load_u64(offset)?;
output[0] = Val::I64(byte as i64);
Ok(())
}
@@ -174,7 +130,7 @@ pub(crate) fn output_set(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let (offset, length) = args!(input, (0, i64), (1, i64));
data.output_offset = offset as usize;
@@ -189,7 +145,7 @@ pub(crate) fn alloc(
mut caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let offs = data.memory_mut().alloc(input[0].unwrap_i64() as _)?;
output[0] = Val::I64(offs.offset as i64);
@@ -204,7 +160,7 @@ pub(crate) fn free(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let offset = args!(input, 0, i64) as usize;
data.memory_mut().free(offset);
@@ -218,7 +174,7 @@ pub(crate) fn error_set(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let offset = args!(input, 0, i64) as usize;
@@ -240,7 +196,7 @@ pub(crate) fn config_get(
mut caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let plugin = data.plugin_mut();
@@ -265,7 +221,7 @@ pub(crate) fn var_get(
mut caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let plugin = data.plugin_mut();
@@ -292,7 +248,7 @@ pub(crate) fn var_set(
mut caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let plugin = data.plugin_mut();
@@ -305,7 +261,7 @@ pub(crate) fn var_set(
// If the store is larger than 100MB then stop adding things
if size > 1024 * 1024 * 100 && voffset != 0 {
return Err(Trap::new("Variable store is full"));
return Err(Error::msg("Variable store is full"));
}
let key_offs = args!(input, 0, i64) as usize;
@@ -332,12 +288,12 @@ pub(crate) fn http_request(
#[allow(unused_mut)] mut caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
#[cfg(not(feature = "http"))]
{
let _ = (caller, input);
output[0] = Val::I64(0 as i64);
output[0] = Val::I64(0);
error!("http_request is not enabled");
return Ok(());
}
@@ -349,14 +305,13 @@ pub(crate) fn http_request(
let http_req_offset = args!(input, 0, i64) as usize;
let req: extism_manifest::HttpRequest =
serde_json::from_slice(data.memory().get(http_req_offset)?)
.map_err(|_| Trap::new("Invalid http request"))?;
serde_json::from_slice(data.memory().get(http_req_offset)?)?;
let body_offset = args!(input, 1, i64) as usize;
let url = match url::Url::parse(&req.url) {
Ok(u) => u,
Err(e) => return Err(Trap::new(format!("Invalid URL: {e:?}"))),
Err(e) => return Err(Error::msg(format!("Invalid URL: {e:?}"))),
};
let allowed_hosts = &data.plugin().manifest.as_ref().allowed_hosts;
let host_str = url.host_str().unwrap_or_default();
@@ -370,7 +325,7 @@ pub(crate) fn http_request(
pat.matches(host_str)
});
if !allowed_hosts.is_empty() && !host_matches_allowed {
return Err(Trap::new(format!(
return Err(Error::msg(format!(
"HTTP request to {} is not allowed",
req.url
)));
@@ -383,20 +338,20 @@ pub(crate) fn http_request(
r = r.set(k, v);
}
let mut res = if body_offset > 0 {
let res = if body_offset > 0 {
let buf = data.memory().get(body_offset)?;
r.send_bytes(buf)
.map_err(|e| Trap::new(&format!("Request error: {e:?}")))?
.into_reader()
let res = r.send_bytes(buf)?;
data.http_status = res.status();
res.into_reader()
} else {
r.call()
.map_err(|e| Trap::new(format!("{:?}", e)))?
.into_reader()
let res = r.call()?;
data.http_status = res.status();
res.into_reader()
};
let mut buf = Vec::new();
res.read_to_end(&mut buf)
.map_err(|e| Trap::new(format!("{:?}", e)))?;
res.take(1024 * 1024 * 50) // TODO: make this limit configurable
.read_to_end(&mut buf)?;
let mem = data.memory_mut().alloc_bytes(buf)?;
@@ -405,6 +360,19 @@ pub(crate) fn http_request(
}
}
/// Get the status code of the last HTTP request
/// Params: none
/// Returns: i32 (status code)
pub(crate) fn http_status_code(
mut caller: Caller<Internal>,
_input: &[Val],
output: &mut [Val],
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
output[0] = Val::I32(data.http_status as i32);
Ok(())
}
/// Get the length of an allocated block given the offset
/// Params: i64 (offset)
/// Returns: i64 (length or 0)
@@ -412,7 +380,7 @@ pub(crate) fn length(
mut caller: Caller<Internal>,
input: &[Val],
output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &mut Internal = caller.data_mut();
let offset = args!(input, 0, i64) as usize;
if offset == 0 {
@@ -421,7 +389,7 @@ pub(crate) fn length(
}
let length = match data.memory().block_length(offset) {
Some(x) => x,
None => return Err(Trap::new("Unable to find length for offset")),
None => return Err(Error::msg("Unable to find length for offset")),
};
output[0] = Val::I64(length as i64);
Ok(())
@@ -432,7 +400,7 @@ pub fn log(
caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
let data: &Internal = caller.data();
let offset = args!(input, 0, i64) as usize;
let buf = data.memory().get(offset)?;
@@ -451,7 +419,7 @@ pub(crate) fn log_warn(
caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
log(log::Level::Warn, caller, input, _output)
}
@@ -462,7 +430,7 @@ pub(crate) fn log_info(
caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
log(log::Level::Info, caller, input, _output)
}
@@ -473,7 +441,7 @@ pub(crate) fn log_debug(
caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
log(log::Level::Debug, caller, input, _output)
}
@@ -484,6 +452,6 @@ pub(crate) fn log_error(
caller: Caller<Internal>,
input: &[Val],
_output: &mut [Val],
) -> Result<(), Trap> {
) -> Result<(), Error> {
log(log::Level::Error, caller, input, _output)
}

View File

@@ -20,6 +20,7 @@ pub struct Internal {
pub output_length: usize,
pub plugin: *mut Plugin,
pub wasi: Option<Wasi>,
pub http_status: u16,
}
pub struct Wasi {
@@ -42,6 +43,7 @@ impl Internal {
let nn = wasmtime_wasi_nn::WasiNnCtx::new()?;
#[cfg(not(feature = "nn"))]
#[allow(clippy::let_unit_value)]
let nn = ();
Some(Wasi {
@@ -59,6 +61,7 @@ impl Internal {
input: std::ptr::null(),
wasi,
plugin: std::ptr::null_mut(),
http_status: 0,
})
}
@@ -115,7 +118,7 @@ impl Plugin {
$(
concat!("extism_", stringify!($name)) => {
let t = FuncType::new([$($args),*], [$($($r),*)?]);
let f = Func::new(&mut memory.store, t, export::$name);
let f = Func::new(&mut memory.store, t, pdk::$name);
linker.define(EXPORT_MODULE_NAME, concat!("extism_", stringify!($name)), Extern::Func(f))?;
continue
}
@@ -137,10 +140,8 @@ impl Plugin {
alloc(I64) -> I64;
free(I64);
load_u8(I64) -> I32;
load_u32(I64) -> I32;
load_u64(I64) -> I64;
store_u8(I64, I32);
store_u32(I64, I32);
store_u64(I64, I64);
input_length() -> I64;
input_load_u8(I64) -> I32;
@@ -151,6 +152,7 @@ impl Plugin {
var_get(I64) -> I64;
var_set(I64, I64);
http_request(I64, I64) -> I64;
http_status_code() -> I32;
length(I64) -> I64;
log_warn(I64);
log_info(I64);

View File

@@ -36,29 +36,8 @@ pub unsafe extern "C" fn extism_plugin_new(
) -> PluginIndex {
trace!("Call to extism_plugin_new with wasm pointer {:?}", wasm);
let ctx = &mut *ctx;
let data = std::slice::from_raw_parts(wasm, wasm_size as usize);
let plugin = match Plugin::new(data, with_wasi) {
Ok(x) => x,
Err(e) => {
error!("Error creating Plugin: {:?}", e);
ctx.set_error(e);
return -1;
}
};
// Allocate a new plugin ID
let id: i32 = match ctx.next_id() {
Ok(id) => id,
Err(e) => {
error!("Error creating Plugin: {:?}", e);
ctx.set_error(e);
return -1;
}
};
ctx.plugins.insert(id, plugin);
info!("New plugin added: {id}");
id
ctx.new_plugin(data, with_wasi)
}
/// Update a plugin, keeping the existing ID
@@ -242,12 +221,29 @@ pub unsafe extern "C" fn extism_plugin_call(
None => return plugin.error(format!("Function not found: {name}"), -1),
};
// Call function with offset+length pointing to input data.
let mut results = vec![Val::I32(0)];
// Check the number of results, reject functions with more than 1 result
let n_results = func.ty(&plugin.memory.store).results().len();
if n_results > 1 {
return plugin.error(
format!("Function {name} has {n_results} results, expected 0 or 1"),
-1,
);
}
let mut results = vec![Val::null(); n_results];
match func.call(&mut plugin.memory.store, &[], results.as_mut_slice()) {
Ok(r) => r,
Err(e) => {
plugin.dump_memory();
if let Some(exit) = e.downcast_ref::<wasmtime_wasi::I32Exit>() {
error!("WASI return code: {}", exit.0);
if exit.0 != 0 {
return plugin.error(&e, exit.0);
}
return exit.0;
}
error!("Call: {e:?}");
return plugin.error(e.context("Call failed"), -1);
}
@@ -255,6 +251,12 @@ pub unsafe extern "C" fn extism_plugin_call(
plugin.dump_memory();
// If `results` is empty then the return value is expected to be returned
// in the error block of the func call above using `I32Exit`
if results.is_empty() {
return 0;
}
// Return result to caller
results[0].unwrap_i32()
}

View File

@@ -1,15 +1,16 @@
[package]
name = "extism"
version = "0.0.1-rc.5"
version = "0.0.1"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"
links = "extism"
homepage = "https://extism.org"
repository = "https://github.com/extism/extism"
description = "Extism Host SDK for Rust"
[dependencies]
extism-manifest = { version = "0.0.1-rc.4", path = "../manifest" }
extism-manifest = { version = "0.0.1-rc.6", path = "../manifest" }
extism-runtime = { version = "0.0.1-rc.6", path = "../runtime"}
serde_json = "1"
log = "0.4"
log = "0.4"
thiserror = "1"

View File

@@ -1,10 +0,0 @@
fn main() {
println!("cargo:rustc-link-search=/usr/local/lib");
if let Ok(home) = std::env::var("HOME") {
let path = std::path::PathBuf::from(home).join(".local").join("lib");
println!("cargo:rustc-link-search={}", path.display());
}
println!("cargo:rustc-link-lib=extism");
}

View File

@@ -1,8 +1,6 @@
use crate::*;
pub struct Context {
pub(crate) pointer: *mut bindings::ExtismContext,
}
pub struct Context(pub(crate) std::sync::Arc<std::sync::Mutex<extism_runtime::Context>>);
impl Default for Context {
fn default() -> Context {
@@ -13,25 +11,20 @@ impl Default for Context {
impl Context {
/// Create a new context
pub fn new() -> Context {
let pointer = unsafe { bindings::extism_context_new() };
Context { pointer }
Context(std::sync::Arc::new(std::sync::Mutex::new(
extism_runtime::Context::new(),
)))
}
/// Remove all registered plugins
pub fn reset(&mut self) {
unsafe { bindings::extism_context_reset(self.pointer) }
unsafe { bindings::extism_context_reset(&mut *self.lock()) }
}
}
unsafe impl Send for Context {}
unsafe impl Sync for Context {}
impl Drop for Context {
fn drop(&mut self) {
if self.pointer.is_null() {
return;
pub(crate) fn lock(&self) -> std::sync::MutexGuard<extism_runtime::Context> {
match self.0.lock() {
Ok(x) => x,
Err(x) => x.into_inner(),
}
unsafe { bindings::extism_context_free(self.pointer) }
self.pointer = std::ptr::null_mut();
}
}

View File

@@ -1,9 +1,5 @@
use std::collections::BTreeMap;
use extism_manifest::Manifest;
#[allow(non_camel_case_types)]
pub(crate) mod bindings;
pub use extism_manifest::{self as manifest, Manifest};
pub use extism_runtime::sdk as bindings;
mod context;
mod plugin;
@@ -11,17 +7,16 @@ mod plugin;
pub use context::Context;
pub use plugin::Plugin;
#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unable to load plugin: {0}")]
UnableToLoadPlugin(String),
#[error("{0}")]
Message(String),
Json(serde_json::Error),
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::Json(e)
}
#[error("JSON: {0}")]
Json(#[from] serde_json::Error),
#[error("Runtime: {0}")]
Runtime(#[from] extism_runtime::Error),
}
/// Gets the version of Extism
@@ -54,7 +49,7 @@ mod tests {
let wasm_start = Instant::now();
set_log_file("test.log", Some(log::Level::Info));
let context = Context::new();
let plugin = Plugin::new(&context, WASM, false).unwrap();
let mut plugin = Plugin::new(&context, WASM, false).unwrap();
println!("register loaded plugin: {:?}", wasm_start.elapsed());
let repeat = 1182;
@@ -146,20 +141,20 @@ mod tests {
use std::io::Write;
std::thread::spawn(|| {
let context = Context::new();
let plugin = Plugin::new(&context, WASM, false).unwrap();
let mut plugin = Plugin::new(&context, WASM, false).unwrap();
let output = plugin.call("count_vowels", "this is a test").unwrap();
std::io::stdout().write_all(output).unwrap();
});
std::thread::spawn(|| {
let context = Context::new();
let plugin = Plugin::new(&context, WASM, false).unwrap();
let mut plugin = Plugin::new(&context, WASM, false).unwrap();
let output = plugin.call("count_vowels", "this is a test aaa").unwrap();
std::io::stdout().write_all(output).unwrap();
});
let context = Context::new();
let plugin = Plugin::new(&context, WASM, false).unwrap();
let mut plugin = Plugin::new(&context, WASM, false).unwrap();
let output = plugin.call("count_vowels", "abc123").unwrap();
std::io::stdout().write_all(output).unwrap();
}

View File

@@ -1,16 +1,18 @@
use crate::*;
use std::collections::BTreeMap;
pub struct Plugin<'a> {
id: bindings::ExtismPlugin,
id: extism_runtime::PluginIndex,
context: &'a Context,
}
impl<'a> Plugin<'a> {
/// Create plugin from a known-good ID
///
/// # Safety
/// This function does not check to ensure the provided ID is valid
pub unsafe fn from_id(id: i32, context: &'a Context) -> Plugin<'a> {
Plugin {
id,
context: context,
}
Plugin { id, context }
}
pub fn as_i32(&self) -> i32 {
@@ -19,7 +21,7 @@ impl<'a> Plugin<'a> {
/// Create a new plugin from the given manifest
pub fn new_with_manifest(
ctx: &'a Context,
ctx: &'a mut Context,
manifest: &Manifest,
wasi: bool,
) -> Result<Plugin<'a>, Error> {
@@ -29,17 +31,10 @@ impl<'a> Plugin<'a> {
/// Create a new plugin from a WASM module
pub fn new(ctx: &'a Context, data: impl AsRef<[u8]>, wasi: bool) -> Result<Plugin, Error> {
let plugin = unsafe {
bindings::extism_plugin_new(
ctx.pointer,
data.as_ref().as_ptr(),
data.as_ref().len() as u64,
wasi,
)
};
let plugin = ctx.lock().new_plugin(data, wasi);
if plugin < 0 {
let err = unsafe { bindings::extism_error(ctx.pointer, -1) };
let err = unsafe { bindings::extism_error(&mut *ctx.lock(), -1) };
let buf = unsafe { std::ffi::CStr::from_ptr(err) };
let buf = buf.to_str().unwrap().to_string();
return Err(Error::UnableToLoadPlugin(buf));
@@ -55,7 +50,7 @@ impl<'a> Plugin<'a> {
pub fn update(&mut self, data: impl AsRef<[u8]>, wasi: bool) -> Result<(), Error> {
let b = unsafe {
bindings::extism_plugin_update(
self.context.pointer,
&mut *self.context.lock(),
self.id,
data.as_ref().as_ptr(),
data.as_ref().len() as u64,
@@ -66,7 +61,7 @@ impl<'a> Plugin<'a> {
return Ok(());
}
let err = unsafe { bindings::extism_error(self.context.pointer, -1) };
let err = unsafe { bindings::extism_error(&mut *self.context.lock(), -1) };
if !err.is_null() {
let s = unsafe { std::ffi::CStr::from_ptr(err) };
return Err(Error::Message(s.to_str().unwrap().to_string()));
@@ -82,11 +77,11 @@ impl<'a> Plugin<'a> {
}
/// Set configuration values
pub fn set_config(&self, config: &BTreeMap<String, Option<String>>) -> Result<(), Error> {
pub fn set_config(&mut self, config: &BTreeMap<String, Option<String>>) -> Result<(), Error> {
let encoded = serde_json::to_vec(config)?;
unsafe {
bindings::extism_plugin_config(
self.context.pointer,
&mut *self.context.lock(),
self.id,
encoded.as_ptr() as *const _,
encoded.len() as u64,
@@ -96,7 +91,7 @@ impl<'a> Plugin<'a> {
}
/// Set configuration values, builder-style
pub fn with_config(self, config: &BTreeMap<String, Option<String>>) -> Result<Self, Error> {
pub fn with_config(mut self, config: &BTreeMap<String, Option<String>>) -> Result<Self, Error> {
self.set_config(config)?;
Ok(self)
}
@@ -106,7 +101,7 @@ impl<'a> Plugin<'a> {
let name = std::ffi::CString::new(name.as_ref()).expect("Invalid function name");
unsafe {
bindings::extism_plugin_function_exists(
self.context.pointer,
&mut *self.context.lock(),
self.id,
name.as_ptr() as *const _,
)
@@ -114,11 +109,11 @@ impl<'a> Plugin<'a> {
}
/// Call a function with the given input
pub fn call(&self, name: impl AsRef<str>, input: impl AsRef<[u8]>) -> Result<&[u8], Error> {
pub fn call(&mut self, name: impl AsRef<str>, input: impl AsRef<[u8]>) -> Result<&[u8], Error> {
let name = std::ffi::CString::new(name.as_ref()).expect("Invalid function name");
let rc = unsafe {
bindings::extism_plugin_call(
self.context.pointer,
&mut *self.context.lock(),
self.id,
name.as_ptr() as *const _,
input.as_ref().as_ptr() as *const _,
@@ -127,7 +122,7 @@ impl<'a> Plugin<'a> {
};
if rc != 0 {
let err = unsafe { bindings::extism_error(self.context.pointer, self.id) };
let err = unsafe { bindings::extism_error(&mut *self.context.lock(), self.id) };
if !err.is_null() {
let s = unsafe { std::ffi::CStr::from_ptr(err) };
return Err(Error::Message(s.to_str().unwrap().to_string()));
@@ -137,9 +132,9 @@ impl<'a> Plugin<'a> {
}
let out_len =
unsafe { bindings::extism_plugin_output_length(self.context.pointer, self.id) };
unsafe { bindings::extism_plugin_output_length(&mut *self.context.lock(), self.id) };
unsafe {
let ptr = bindings::extism_plugin_output_data(self.context.pointer, self.id);
let ptr = bindings::extism_plugin_output_data(&mut *self.context.lock(), self.id);
Ok(std::slice::from_raw_parts(ptr, out_len as usize))
}
}
@@ -147,9 +142,6 @@ impl<'a> Plugin<'a> {
impl<'a> Drop for Plugin<'a> {
fn drop(&mut self) {
if self.context.pointer.is_null() {
return;
}
unsafe { bindings::extism_plugin_free(self.context.pointer, self.id) }
unsafe { bindings::extism_plugin_free(&mut *self.context.lock(), self.id) }
}
}