YmOUop9H&
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
diff --git a/zig/src/current_plugin.zig b/zig/src/current_plugin.zig
index 3fdf5ac0d..b965d92e1 100644
--- a/zig/src/current_plugin.zig
+++ b/zig/src/current_plugin.zig
@@ -13,7 +13,7 @@ pub fn getMemory(self: Self, offset: u64) []const u8 {
const len = c.extism_current_plugin_memory_length(self.c_currplugin, offset);
const c_data = c.extism_current_plugin_memory(self.c_currplugin);
const data: [*:0]u8 = std.mem.span(c_data);
- return data[offset .. len + 1];
+ return data[offset .. offset + len];
}
pub fn alloc(self: *Self, n: u64) u64 {
diff --git a/zig/src/utils.zig b/zig/src/utils.zig
index 7578cdc06..c50cea970 100644
--- a/zig/src/utils.zig
+++ b/zig/src/utils.zig
@@ -81,7 +81,7 @@ fn stringify(
try out_stream.writeByte('{');
var field_output = false;
var child_options = options;
- child_options.whitespace.indent_level += 1;
+ child_options.whitespace = .indent_2;
inline for (S.fields) |Field| {
// don't include void fields
if (Field.type == void) continue;
@@ -103,18 +103,14 @@ fn stringify(
} else {
try out_stream.writeByte(',');
}
- try child_options.whitespace.outputIndent(out_stream);
try json.encodeJsonString(Field.name, options, out_stream);
try out_stream.writeByte(':');
- if (child_options.whitespace.separator) {
+ if (child_options.whitespace != .minified) {
try out_stream.writeByte(' ');
}
try stringify(@field(value, Field.name), child_options, out_stream);
}
}
- if (field_output) {
- try options.whitespace.outputIndent(out_stream);
- }
try out_stream.writeByte('}');
return;
},
@@ -133,24 +129,19 @@ fn stringify(
},
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
.Slice => {
- if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {
+ if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
try json.encodeJsonString(value, options, out_stream);
return;
}
try out_stream.writeByte('[');
var child_options = options;
- child_options.whitespace.indent_level += 1;
for (value, 0..) |x, i| {
if (i != 0) {
try out_stream.writeByte(',');
}
- try child_options.whitespace.outputIndent(out_stream);
try stringify(x, child_options, out_stream);
}
- if (value.len != 0) {
- try options.whitespace.outputIndent(out_stream);
- }
try out_stream.writeByte(']');
return;
},
From ab4995dac2b6376e9d402b5680cd835eba1a665f Mon Sep 17 00:00:00 2001
From: zach
Date: Fri, 28 Jul 2023 15:08:10 -0700
Subject: [PATCH 006/176] fix(python): store reference to host functions on
Plugin (#399)
This should fix the issue @neuronicnobody ran into with a segfault
depending on the scope of the host function definition
---
python/extism/extism.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/python/extism/extism.py b/python/extism/extism.py
index e0dc38f7e..32a04a63e 100644
--- a/python/extism/extism.py
+++ b/python/extism/extism.py
@@ -263,6 +263,7 @@ def __init__(
context = Context()
wasm = _wasm(plugin)
+ self.functions = functions
# Register plugin
if functions is not None:
@@ -310,6 +311,7 @@ def update(
"""
wasm = _wasm(manifest)
if functions is not None:
+ self.functions = functions
functions = [f.pointer for f in functions]
ptr = _ffi.new("ExtismFunction*[]", functions)
ok = _lib.extism_plugin_update(
From 26b34ed90683816ddfa8f2bc7877c97dfe636da0 Mon Sep 17 00:00:00 2001
From: zach
Date: Mon, 31 Jul 2023 11:25:47 -0700
Subject: [PATCH 007/176] fix: Update more SDKs to store a reference to host
functions in the Plugin type (#401)
Similar to https://github.com/extism/extism/pull/399
---
extism.go | 10 ++++++----
ocaml/lib/plugin.ml | 4 +++-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/extism.go b/extism.go
index 15319cb8f..1c0e0cd5a 100644
--- a/extism.go
+++ b/extism.go
@@ -173,8 +173,9 @@ func (ctx *Context) Free() {
// Plugin is used to call WASM functions
type Plugin struct {
- ctx *Context
- id int32
+ ctx *Context
+ id int32
+ functions []Function
}
type WasmData struct {
@@ -272,7 +273,7 @@ func register(ctx *Context, data []byte, functions []Function, wasi bool) (Plugi
)
}
- return Plugin{id: int32(plugin), ctx: ctx}, nil
+ return Plugin{id: int32(plugin), ctx: ctx, functions: functions}, nil
}
func update(ctx *Context, plugin int32, data []byte, functions []Function, wasi bool) error {
@@ -361,7 +362,7 @@ func (p *Plugin) Update(module io.Reader, functions []Function, wasi bool) error
if err != nil {
return err
}
-
+ p.functions = functions
return update(p.ctx, p.id, wasm, functions, wasi)
}
@@ -372,6 +373,7 @@ func (p *Plugin) UpdateManifest(manifest Manifest, functions []Function, wasi bo
return err
}
+ p.functions = functions
return update(p.ctx, p.id, data, functions, wasi)
}
diff --git a/ocaml/lib/plugin.ml b/ocaml/lib/plugin.ml
index 8cdc5a3fd..712e20522 100644
--- a/ocaml/lib/plugin.ml
+++ b/ocaml/lib/plugin.ml
@@ -77,7 +77,9 @@ let update plugin ?config ?(wasi = false) ?(functions = []) wasm =
| Some msg -> Error (`Msg msg)
else if not (set_config plugin config) then
Error (`Msg "call to set_config failed")
- else Ok ()
+ else
+ let () = plugin.functions <- functions in
+ Ok ()
let update_manifest plugin ?wasi manifest =
let data = Manifest.to_json manifest in
From 41450a03a9e441ce8a21035a285558e5ca30a926 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 14:59:19 -0500
Subject: [PATCH 008/176] chore(deps-dev): Update minitest requirement from ~>
5.18.0 to ~> 5.19.0 in /ruby (#402)
Updates the requirements on
[minitest](https://github.com/minitest/minitest) to permit the latest
version.
Changelog
Sourced from minitest's
changelog.
=== 5.19.0 / 2023-07-26
-
2 minor enhancements:
- Add metadata lazy accessor to Runnable / Result. (matteeyah)
- Only load minitest/unit (aka ancient MiniTest compatibility layer)
if ENV["MT_COMPAT"]
-
1 bug fix:
- Minitest::TestTask enthusiastically added itself to default.
(ParadoxV5)
=== 5.18.1 / 2023-06-16
-
3 bug fixes:
- Avoid extra string allocations when filtering tests.
(tenderlove)
- Only mention deprecated ENV['N'] if it is an integer string.
- Push up test_order to Minitest::Runnable to fix minitest/hell.
(koic)
=== 5.18.0 / 2023-03-04
-
2 major enhancements:
- Added assert_pattern & refute_pattern for pattern matching.
(flavorjones)
- Added matching must_pattern_match & wont_pattern_match to
minitest/spec.
-
1 bug fix:
- Support the new message format of NameError in Ruby 3.3 (mame)
=== 5.17.0 / 2022-12-31
-
1 minor enhancement:
- Refactor setup hooks into a SETUP_METHODS constant. (MSP-Greg)
-
3 bug fixes:
- Fix kwargs for Mock calls to delegator. (blowmage)
- Fix kwargs for expectations. (bobmazanec, blowmage)
- Remove check for .b method. (tenderlove)
=== 5.16.3 / 2022-08-17
-
2 bug fixes:
- Fixed exception sanitization by removing TypeError restriction on
rescue.
- Use A instead of deprecated TESTOPTS in rake test:slow.
(davidstosik)
=== 5.16.2 / 2022-07-03
... (truncated)
Commits
96a9972
prepped for release
de80282
+ Add metadata lazy accessor to Runnable / Result. (matteeyah)
4795997
- Minitest::TestTask enthusiastically added itself to default.
(ParadoxV5)
a2c6c18
+ Only load minitest/unit (aka ancient MiniTest compatibility layer) if
ENV["...
5f05692
Replace 'MiniTest' with 'Minitest' in example code. (sambostock)
31da3c6
prepped for release
a90720a
Removed 2.6 from CI.
ca42951
- Avoid extra string allocations when filtering tests. (tenderlove)
e6f4a85
- Only mention deprecated ENV['N'] if it is an integer string.
a9fa045
- Push up test_order to Minitest::Runnable to fix minitest/hell.
(koic)
- Additional commits viewable in compare
view
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)
---
Dependabot commands and options
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)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
ruby/Gemfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ruby/Gemfile b/ruby/Gemfile
index 6c6f203c0..c3c43cae3 100644
--- a/ruby/Gemfile
+++ b/ruby/Gemfile
@@ -11,5 +11,5 @@ gem "ffi", "~> 1.15.5"
group :development do
gem "yard", "~> 0.9.28"
gem "rufo", "~> 0.13.0"
- gem "minitest", "~> 5.18.0"
+ gem "minitest", "~> 5.19.0"
end
From a3053a9ecc8ec1d3943343c3feede996210e5b1e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 14:59:43 -0500
Subject: [PATCH 009/176] chore(deps-dev): Bump jest from 29.6.1 to 29.6.2 in
/node (#403)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest)
from 29.6.1 to 29.6.2.
Release notes
Sourced from jest's
releases.
v29.6.2
Fixes
[jest-circus]
Fix snapshot matchers in concurrent tests
when nr of tests exceeds maxConcurrency
(#14335)
[@jest/core]
When running global setup and teardown, do
not try to change the message
property of the thrown error
object when the message
property is unwritable (#14113)
[jest-snapshot]
Move @types/prettier
from
dependencies
to devDependencies
(#14328)
[jest-snapshot]
Throw an explicit error if Prettier v3
is used (#14367)
[jest-reporters]
Add "skipped" and
"todo" symbols to Github Actions Reporter (#14309)
Chore & Maintenance
[@jest/core]
Use pluralize
from
jest-util
rather than own internal (#14322)
New Contributors
Full Changelog: https://github.com/jestjs/jest/compare/v29.6.1...v29.6.2
Changelog
Sourced from jest's
changelog.
29.6.2
Fixes
[jest-circus]
Fix snapshot matchers in concurrent tests
when nr of tests exceeds maxConcurrency
(#14335)
[@jest/core]
When running global setup and teardown, do
not try to change the message
property of the thrown error
object when the message
property is unwritable (#14113)
[jest-snapshot]
Move @types/prettier
from
dependencies
to devDependencies
(#14328)
[jest-snapshot]
Throw an explicit error if Prettier v3
is used (#14367)
[jest-reporters]
Add "skipped" and
"todo" symbols to Github Actions Reporter (#14309)
Chore & Maintenance
[@jest/core]
Use pluralize
from
jest-util
rather than own internal (#14322)
Commits
[](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)
---
Dependabot commands and options
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)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
node/package-lock.json | 524 +++++++++++++++++++++--------------------
1 file changed, 270 insertions(+), 254 deletions(-)
diff --git a/node/package-lock.json b/node/package-lock.json
index 990252fbf..2b3173133 100644
--- a/node/package-lock.json
+++ b/node/package-lock.json
@@ -654,16 +654,16 @@
}
},
"node_modules/@jest/console": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
- "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz",
+ "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
"slash": "^3.0.0"
},
"engines": {
@@ -671,15 +671,15 @@
}
},
"node_modules/@jest/core": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
- "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz",
+ "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
- "@jest/reporters": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
+ "@jest/console": "^29.6.2",
+ "@jest/reporters": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
@@ -688,20 +688,20 @@
"exit": "^0.1.2",
"graceful-fs": "^4.2.9",
"jest-changed-files": "^29.5.0",
- "jest-config": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-message-util": "^29.6.1",
+ "jest-config": "^29.6.2",
+ "jest-haste-map": "^29.6.2",
+ "jest-message-util": "^29.6.2",
"jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-resolve-dependencies": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
- "jest-watcher": "^29.6.1",
+ "jest-resolve": "^29.6.2",
+ "jest-resolve-dependencies": "^29.6.2",
+ "jest-runner": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
+ "jest-watcher": "^29.6.2",
"micromatch": "^4.0.4",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.2",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
},
@@ -718,37 +718,37 @@
}
},
"node_modules/@jest/environment": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
- "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz",
+ "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==",
"dev": true,
"dependencies": {
- "@jest/fake-timers": "^29.6.1",
+ "@jest/fake-timers": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-mock": "^29.6.1"
+ "jest-mock": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz",
+ "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==",
"dev": true,
"dependencies": {
- "expect": "^29.6.1",
- "jest-snapshot": "^29.6.1"
+ "expect": "^29.6.2",
+ "jest-snapshot": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
- "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz",
+ "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==",
"dev": true,
"dependencies": {
"jest-get-type": "^29.4.3"
@@ -758,47 +758,47 @@
}
},
"node_modules/@jest/fake-timers": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
- "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz",
+ "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
"@sinonjs/fake-timers": "^10.0.2",
"@types/node": "*",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-message-util": "^29.6.2",
+ "jest-mock": "^29.6.2",
+ "jest-util": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/globals": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
- "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz",
+ "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
+ "@jest/environment": "^29.6.2",
+ "@jest/expect": "^29.6.2",
"@jest/types": "^29.6.1",
- "jest-mock": "^29.6.1"
+ "jest-mock": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/reporters": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
- "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz",
+ "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==",
"dev": true,
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
+ "@jest/console": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
"@jest/types": "^29.6.1",
"@jridgewell/trace-mapping": "^0.3.18",
"@types/node": "*",
@@ -812,9 +812,9 @@
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
"istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-worker": "^29.6.2",
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0",
@@ -859,12 +859,12 @@
}
},
"node_modules/@jest/test-result": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
- "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz",
+ "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
+ "@jest/console": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/istanbul-lib-coverage": "^2.0.0",
"collect-v8-coverage": "^1.0.0"
@@ -874,14 +874,14 @@
}
},
"node_modules/@jest/test-sequencer": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
- "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz",
+ "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.6.1",
+ "@jest/test-result": "^29.6.2",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.2",
"slash": "^3.0.0"
},
"engines": {
@@ -889,9 +889,9 @@
}
},
"node_modules/@jest/transform": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
- "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz",
+ "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
@@ -902,9 +902,9 @@
"convert-source-map": "^2.0.0",
"fast-json-stable-stringify": "^2.1.0",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.2",
"jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.2",
"micromatch": "^4.0.4",
"pirates": "^4.0.4",
"slash": "^3.0.0",
@@ -1132,12 +1132,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
"integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw=="
},
- "node_modules/@types/prettier": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
- "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
- "dev": true
- },
"node_modules/@types/ref-array-di": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/ref-array-di/-/ref-array-di-1.2.5.tgz",
@@ -1304,12 +1298,12 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/babel-jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
- "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz",
+ "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==",
"dev": true,
"dependencies": {
- "@jest/transform": "^29.6.1",
+ "@jest/transform": "^29.6.2",
"@types/babel__core": "^7.1.14",
"babel-plugin-istanbul": "^6.1.1",
"babel-preset-jest": "^29.5.0",
@@ -1654,10 +1648,18 @@
}
},
"node_modules/dedent": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
- "dev": true
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.0.tgz",
+ "integrity": "sha512-3sSQTYoWKGcRHmHl6Y6opLpRJH55bxeGQ0Y1LCI5pZzUXvokVkj0FC4bi7uEwazxA9FQZ0Nv067Zt5kSUvXxEA==",
+ "dev": true,
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
},
"node_modules/deepmerge": {
"version": "4.3.1",
@@ -1825,17 +1827,17 @@
}
},
"node_modules/expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz",
+ "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==",
"dev": true,
"dependencies": {
- "@jest/expect-utils": "^29.6.1",
+ "@jest/expect-utils": "^29.6.2",
"@types/node": "*",
"jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2193,17 +2195,17 @@
}
},
"node_modules/istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
+ "make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
}
},
"node_modules/istanbul-lib-source-maps": {
@@ -2221,9 +2223,9 @@
}
},
"node_modules/istanbul-reports": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+ "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
@@ -2234,15 +2236,15 @@
}
},
"node_modules/jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
- "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz",
+ "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.6.1",
+ "@jest/core": "^29.6.2",
"@jest/types": "^29.6.1",
"import-local": "^3.0.2",
- "jest-cli": "^29.6.1"
+ "jest-cli": "^29.6.2"
},
"bin": {
"jest": "bin/jest.js"
@@ -2273,28 +2275,28 @@
}
},
"node_modules/jest-circus": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
- "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz",
+ "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
- "@jest/test-result": "^29.6.1",
+ "@jest/environment": "^29.6.2",
+ "@jest/expect": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
"co": "^4.6.0",
- "dedent": "^0.7.0",
+ "dedent": "^1.0.0",
"is-generator-fn": "^2.0.0",
- "jest-each": "^29.6.1",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-each": "^29.6.2",
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
"p-limit": "^3.1.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.2",
"pure-rand": "^6.0.0",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
@@ -2304,21 +2306,21 @@
}
},
"node_modules/jest-cli": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
- "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz",
+ "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.6.1",
- "@jest/test-result": "^29.6.1",
+ "@jest/core": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
"@jest/types": "^29.6.1",
"chalk": "^4.0.0",
"exit": "^0.1.2",
"graceful-fs": "^4.2.9",
"import-local": "^3.0.2",
- "jest-config": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-config": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
"prompts": "^2.0.1",
"yargs": "^17.3.1"
},
@@ -2338,31 +2340,31 @@
}
},
"node_modules/jest-config": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
- "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz",
+ "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.6.1",
+ "@jest/test-sequencer": "^29.6.2",
"@jest/types": "^29.6.1",
- "babel-jest": "^29.6.1",
+ "babel-jest": "^29.6.2",
"chalk": "^4.0.0",
"ci-info": "^3.2.0",
"deepmerge": "^4.2.2",
"glob": "^7.1.3",
"graceful-fs": "^4.2.9",
- "jest-circus": "^29.6.1",
- "jest-environment-node": "^29.6.1",
+ "jest-circus": "^29.6.2",
+ "jest-environment-node": "^29.6.2",
"jest-get-type": "^29.4.3",
"jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-resolve": "^29.6.2",
+ "jest-runner": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
"micromatch": "^4.0.4",
"parse-json": "^5.2.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.2",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
},
@@ -2383,15 +2385,15 @@
}
},
"node_modules/jest-diff": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
- "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz",
+ "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"diff-sequences": "^29.4.3",
"jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2410,33 +2412,33 @@
}
},
"node_modules/jest-each": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
- "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz",
+ "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
"chalk": "^4.0.0",
"jest-get-type": "^29.4.3",
- "jest-util": "^29.6.1",
- "pretty-format": "^29.6.1"
+ "jest-util": "^29.6.2",
+ "pretty-format": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-environment-node": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
- "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz",
+ "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
+ "@jest/environment": "^29.6.2",
+ "@jest/fake-timers": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-mock": "^29.6.2",
+ "jest-util": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2452,9 +2454,9 @@
}
},
"node_modules/jest-haste-map": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
- "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz",
+ "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
@@ -2464,8 +2466,8 @@
"fb-watchman": "^2.0.0",
"graceful-fs": "^4.2.9",
"jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-util": "^29.6.2",
+ "jest-worker": "^29.6.2",
"micromatch": "^4.0.4",
"walker": "^1.0.8"
},
@@ -2477,37 +2479,37 @@
}
},
"node_modules/jest-leak-detector": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
- "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz",
+ "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==",
"dev": true,
"dependencies": {
"jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-matcher-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
- "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz",
+ "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
- "jest-diff": "^29.6.1",
+ "jest-diff": "^29.6.2",
"jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-message-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
- "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz",
+ "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
@@ -2516,7 +2518,7 @@
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"micromatch": "^4.0.4",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.2",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
@@ -2525,14 +2527,14 @@
}
},
"node_modules/jest-mock": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
- "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz",
+ "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-util": "^29.6.1"
+ "jest-util": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2565,17 +2567,17 @@
}
},
"node_modules/jest-resolve": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
- "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz",
+ "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.2",
"jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-util": "^29.6.2",
+ "jest-validate": "^29.6.2",
"resolve": "^1.20.0",
"resolve.exports": "^2.0.0",
"slash": "^3.0.0"
@@ -2585,43 +2587,43 @@
}
},
"node_modules/jest-resolve-dependencies": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
- "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz",
+ "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==",
"dev": true,
"dependencies": {
"jest-regex-util": "^29.4.3",
- "jest-snapshot": "^29.6.1"
+ "jest-snapshot": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-runner": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
- "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz",
+ "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
- "@jest/environment": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
+ "@jest/console": "^29.6.2",
+ "@jest/environment": "^29.6.2",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
"graceful-fs": "^4.2.9",
"jest-docblock": "^29.4.3",
- "jest-environment-node": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-leak-detector": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-resolve": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-watcher": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-environment-node": "^29.6.2",
+ "jest-haste-map": "^29.6.2",
+ "jest-leak-detector": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-resolve": "^29.6.2",
+ "jest-runtime": "^29.6.2",
+ "jest-util": "^29.6.2",
+ "jest-watcher": "^29.6.2",
+ "jest-worker": "^29.6.2",
"p-limit": "^3.1.0",
"source-map-support": "0.5.13"
},
@@ -2630,17 +2632,17 @@
}
},
"node_modules/jest-runtime": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
- "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz",
+ "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/globals": "^29.6.1",
+ "@jest/environment": "^29.6.2",
+ "@jest/fake-timers": "^29.6.2",
+ "@jest/globals": "^29.6.2",
"@jest/source-map": "^29.6.0",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
+ "@jest/test-result": "^29.6.2",
+ "@jest/transform": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
@@ -2648,13 +2650,13 @@
"collect-v8-coverage": "^1.0.0",
"glob": "^7.1.3",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
+ "jest-haste-map": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-mock": "^29.6.2",
"jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-resolve": "^29.6.2",
+ "jest-snapshot": "^29.6.2",
+ "jest-util": "^29.6.2",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
},
@@ -2663,9 +2665,9 @@
}
},
"node_modules/jest-snapshot": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
- "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz",
+ "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
@@ -2673,21 +2675,20 @@
"@babel/plugin-syntax-jsx": "^7.7.2",
"@babel/plugin-syntax-typescript": "^7.7.2",
"@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.6.1",
- "@jest/transform": "^29.6.1",
+ "@jest/expect-utils": "^29.6.2",
+ "@jest/transform": "^29.6.2",
"@jest/types": "^29.6.1",
- "@types/prettier": "^2.1.5",
"babel-preset-current-node-syntax": "^1.0.0",
"chalk": "^4.0.0",
- "expect": "^29.6.1",
+ "expect": "^29.6.2",
"graceful-fs": "^4.2.9",
- "jest-diff": "^29.6.1",
+ "jest-diff": "^29.6.2",
"jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-matcher-utils": "^29.6.2",
+ "jest-message-util": "^29.6.2",
+ "jest-util": "^29.6.2",
"natural-compare": "^1.4.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.2",
"semver": "^7.5.3"
},
"engines": {
@@ -2710,9 +2711,9 @@
}
},
"node_modules/jest-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
- "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz",
+ "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
@@ -2727,9 +2728,9 @@
}
},
"node_modules/jest-validate": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
- "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz",
+ "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==",
"dev": true,
"dependencies": {
"@jest/types": "^29.6.1",
@@ -2737,7 +2738,7 @@
"chalk": "^4.0.0",
"jest-get-type": "^29.4.3",
"leven": "^3.1.0",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2756,18 +2757,18 @@
}
},
"node_modules/jest-watcher": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
- "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz",
+ "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.6.1",
+ "@jest/test-result": "^29.6.2",
"@jest/types": "^29.6.1",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.2",
"string-length": "^4.0.1"
},
"engines": {
@@ -2775,13 +2776,13 @@
}
},
"node_modules/jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
+ "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
"dev": true,
"dependencies": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.2",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -2920,20 +2921,35 @@
"dev": true
},
"node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"dependencies": {
- "semver": "^6.0.0"
+ "semver": "^7.5.3"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -3246,9 +3262,9 @@
}
},
"node_modules/pretty-format": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
- "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
+ "version": "29.6.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz",
+ "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==",
"dev": true,
"dependencies": {
"@jest/schemas": "^29.6.0",
From 3219d79a8f3c01583d4f93207f148e9fa81d48ff Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 14:59:52 -0500
Subject: [PATCH 010/176] chore(deps-dev): Bump @types/node from 20.4.2 to
20.4.5 in /node (#404)
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.4.2 to 20.4.5.
Commits
[](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)
---
Dependabot commands and options
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)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
node/package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/node/package-lock.json b/node/package-lock.json
index 2b3173133..5d6db9ced 100644
--- a/node/package-lock.json
+++ b/node/package-lock.json
@@ -1128,9 +1128,9 @@
}
},
"node_modules/@types/node": {
- "version": "20.4.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
- "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw=="
+ "version": "20.4.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.5.tgz",
+ "integrity": "sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg=="
},
"node_modules/@types/ref-array-di": {
"version": "1.2.5",
From baa060d062e46b27fce0f50868ec1b3d1644bcf1 Mon Sep 17 00:00:00 2001
From: zach
Date: Mon, 31 Jul 2023 16:52:01 -0700
Subject: [PATCH 011/176] feat: Haskell host functions (#400)
---
haskell/Example.hs | 19 ++-
haskell/extism.cabal | 4 +-
haskell/manifest/Extism/JSON.hs | 6 +-
haskell/manifest/extism-manifest.cabal | 2 +-
haskell/src/Extism.hs | 162 +++++++++++++++++++------
haskell/src/Extism/Bindings.hs | 92 ++++++++++++++
haskell/src/Extism/CurrentPlugin.hs | 48 ++++++++
haskell/test/Test.hs | 20 ++-
runtime/extism.h | 2 +-
runtime/src/internal.rs | 7 +-
runtime/src/sdk.rs | 7 +-
11 files changed, 315 insertions(+), 54 deletions(-)
create mode 100644 haskell/src/Extism/CurrentPlugin.hs
diff --git a/haskell/Example.hs b/haskell/Example.hs
index 9dd3c9d07..04eaea99f 100644
--- a/haskell/Example.hs
+++ b/haskell/Example.hs
@@ -1,15 +1,24 @@
module Main where
import Extism
+import Extism.CurrentPlugin
import Extism.Manifest(manifest, wasmFile)
unwrap (Right x) = x
unwrap (Left (ExtismError msg)) = do
error msg
+hello plugin params msg = do
+ putStrLn "Hello from Haskell!"
+ putStrLn msg
+ offs <- allocBytes plugin (toByteString "{\"count\": 999}")
+ return [toI64 offs]
+
main = do
- let m = manifest [wasmFile "../wasm/code.wasm"]
- plugin <- unwrap <$> Extism.createPluginFromManifest m False
- res <- unwrap <$> Extism.call plugin "count_vowels" (Extism.toByteString "this is a test")
- putStrLn (Extism.fromByteString res)
- Extism.free plugin
+ setLogFile "stdout" Error
+ let m = manifest [wasmFile "../wasm/code-functions.wasm"]
+ f <- hostFunction "hello_world" [I64] [I64] hello "Hello, again"
+ plugin <- unwrap <$> createPluginFromManifest m [f] True
+ res <- unwrap <$> call plugin "count_vowels" (toByteString "this is a test")
+ putStrLn (fromByteString res)
+ free plugin
diff --git a/haskell/extism.cabal b/haskell/extism.cabal
index e1c3859ce..1a5d4c3c2 100644
--- a/haskell/extism.cabal
+++ b/haskell/extism.cabal
@@ -8,10 +8,10 @@ bug-reports: https://github.com/extism/extism
synopsis: Extism bindings
description: Bindings to Extism, the universal plugin system
category: Plugins, WebAssembly
-extra-source-files: CHANGELOG.md
+extra-doc-files: CHANGELOG.md
library
- exposed-modules: Extism
+ exposed-modules: Extism Extism.CurrentPlugin
reexported-modules: Extism.Manifest
hs-source-dirs: src
other-modules: Extism.Bindings
diff --git a/haskell/manifest/Extism/JSON.hs b/haskell/manifest/Extism/JSON.hs
index 5a8a708fc..506ea3ddb 100644
--- a/haskell/manifest/Extism/JSON.hs
+++ b/haskell/manifest/Extism/JSON.hs
@@ -16,8 +16,8 @@ isNull JSNull = True
isNull _ = False
filterNulls obj = [(a, b) | (a, b) <- obj, not (isNull b)]
object x = makeObj $ filterNulls x
-objectWithNulls x = makeObj x
-nonNull x = NotNull x
+objectWithNulls = makeObj
+nonNull = NotNull
null' = Null
(.=) a b = (a, showJSON b)
toNullable (Just x) = NotNull x
@@ -40,7 +40,7 @@ find :: JSON a => String -> JSValue -> Nullable a
find k obj = obj .? k
update :: JSON a => String -> a -> JSValue -> JSValue
-update k v (JSObject obj) = object $ (fromJSObject obj) ++ [k .= v]
+update k v (JSObject obj) = object $ fromJSObject obj ++ [k .= v]
instance JSON a => JSON (Nullable a) where
showJSON (NotNull x) = showJSON x
diff --git a/haskell/manifest/extism-manifest.cabal b/haskell/manifest/extism-manifest.cabal
index 529d758f7..398d9bd53 100644
--- a/haskell/manifest/extism-manifest.cabal
+++ b/haskell/manifest/extism-manifest.cabal
@@ -8,7 +8,7 @@ bug-reports: https://github.com/extism/extism
synopsis: Extism manifest bindings
description: Bindings to Extism WebAssembly manifest
category: Plugins, WebAssembly
-extra-source-files: CHANGELOG.md
+extra-doc-files: CHANGELOG.md
library
exposed-modules: Extism.Manifest Extism.JSON
diff --git a/haskell/src/Extism.hs b/haskell/src/Extism.hs
index f8de37cfc..3c910976c 100644
--- a/haskell/src/Extism.hs
+++ b/haskell/src/Extism.hs
@@ -1,10 +1,21 @@
-module Extism (module Extism, module Extism.Manifest) where
+module Extism (
+ module Extism,
+ module Extism.Manifest,
+ ValType(..),
+ Val(..)
+) where
+
import Data.Int
import Data.Word
import Control.Monad (void)
import Foreign.ForeignPtr
import Foreign.C.String
import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Storable
+import Foreign.StablePtr
+import Foreign.Concurrent
+import Foreign.Marshal.Utils (copyBytes, moveBytes)
import Data.ByteString as B
import Data.ByteString.Internal (c2w, w2c)
import Data.ByteString.Unsafe (unsafeUseAsCString)
@@ -16,10 +27,17 @@ import Extism.Bindings
-- | Context for managing plugins
newtype Context = Context (ForeignPtr ExtismContext)
+-- | Host function
+data Function = Function (ForeignPtr ExtismFunction) (StablePtr ())
+
-- | Plugins can be used to call WASM function
-data Plugin = Plugin Context Int32
+data Plugin = Plugin Context Int32 [Function]
+
+-- | Cancellation handle for Plugins
+newtype CancelHandle = CancelHandle (Ptr ExtismCancelHandle)
-data CancelHandle = CancelHandle (Ptr ExtismCancelHandle)
+-- | Access the plugin that is currently executing from inside a host function
+type CurrentPlugin = Ptr ExtismCurrentPlugin
-- | Log level
data LogLevel = Error | Warn | Info | Debug | Trace deriving (Show)
@@ -53,80 +71,94 @@ reset (Context ctx) =
newContext :: IO Context
newContext = do
ptr <- extism_context_new
- fptr <- newForeignPtr extism_context_free ptr
+ fptr <- Foreign.ForeignPtr.newForeignPtr extism_context_free ptr
return (Context fptr)
-
+
-- | Execute a function with a new 'Context' that is destroyed when it returns
withContext :: (Context -> IO a) -> IO a
withContext f = do
ctx <- newContext
f ctx
+-- | Execute a function with the provided 'Plugin' as a parameter, then frees the 'Plugin'
+-- | before returning the result.
+withPlugin :: (Plugin -> IO a) -> Plugin -> IO a
+withPlugin f plugin = do
+ res <- f plugin
+ free plugin
+ return res
+
-- | Create a 'Plugin' from a WASM module, `useWasi` determines if WASI should
-- | be linked
-plugin :: Context -> B.ByteString -> Bool -> IO (Result Plugin)
-plugin c wasm useWasi =
+plugin :: Context -> B.ByteString -> [Function] -> Bool -> IO (Result Plugin)
+plugin c wasm functions useWasi =
+ let nfunctions = fromIntegral (Prelude.length functions) in
let length = fromIntegral (B.length wasm) in
let wasi = fromInteger (if useWasi then 1 else 0) in
let Context ctx = c in
do
+ funcs <- Prelude.mapM (\(Function ptr _) -> withForeignPtr ptr (\x -> do return x)) functions
withForeignPtr ctx (\ctx -> do
p <- unsafeUseAsCString wasm (\s ->
- extism_plugin_new ctx (castPtr s) length nullPtr 0 wasi )
+ withArray funcs (\funcs ->
+ extism_plugin_new ctx (castPtr s) length funcs nfunctions wasi ))
if p < 0 then do
err <- extism_error ctx (-1)
e <- peekCString err
return $ Left (ExtismError e)
else
- return $ Right (Plugin c p))
-
+ return $ Right (Plugin c p functions))
+
-- | Create a 'Plugin' with its own 'Context'
-createPlugin :: B.ByteString -> Bool -> IO (Result Plugin)
-createPlugin c useWasi = do
+createPlugin :: B.ByteString -> [Function] -> Bool -> IO (Result Plugin)
+createPlugin c functions useWasi = do
ctx <- newContext
- plugin ctx c useWasi
+ plugin ctx c functions useWasi
-- | Create a 'Plugin' from a 'Manifest'
-pluginFromManifest :: Context -> Manifest -> Bool -> IO (Result Plugin)
-pluginFromManifest ctx manifest useWasi =
+pluginFromManifest :: Context -> Manifest -> [Function] -> Bool -> IO (Result Plugin)
+pluginFromManifest ctx manifest functions useWasi =
let wasm = toByteString $ toString manifest in
- plugin ctx wasm useWasi
+ plugin ctx wasm functions useWasi
-- | Create a 'Plugin' with its own 'Context' from a 'Manifest'
-createPluginFromManifest :: Manifest -> Bool -> IO (Result Plugin)
-createPluginFromManifest manifest useWasi = do
+createPluginFromManifest :: Manifest -> [Function] -> Bool -> IO (Result Plugin)
+createPluginFromManifest manifest functions useWasi = do
ctx <- newContext
- pluginFromManifest ctx manifest useWasi
+ pluginFromManifest ctx manifest functions useWasi
-- | Update a 'Plugin' with a new WASM module
-update :: Plugin -> B.ByteString -> Bool -> IO (Result ())
-update (Plugin (Context ctx) id) wasm useWasi =
+update :: Plugin -> B.ByteString -> [Function] -> Bool -> IO (Result Plugin)
+update (Plugin (Context ctx) id _) wasm functions useWasi =
+ let nfunctions = fromIntegral (Prelude.length functions) in
let length = fromIntegral (B.length wasm) in
let wasi = fromInteger (if useWasi then 1 else 0) in
do
- withForeignPtr ctx (\ctx -> do
+ funcs <- Prelude.mapM (\(Function ptr _ ) -> withForeignPtr ptr (\x -> do return x)) functions
+ withForeignPtr ctx (\ctx' -> do
b <- unsafeUseAsCString wasm (\s ->
- extism_plugin_update ctx id (castPtr s) length nullPtr 0 wasi)
+ withArray funcs (\funcs ->
+ extism_plugin_update ctx' id (castPtr s) length funcs nfunctions wasi))
if b <= 0 then do
- err <- extism_error ctx (-1)
+ err <- extism_error ctx' (-1)
e <- peekCString err
return $ Left (ExtismError e)
else
- return (Right ()))
+ return (Right (Plugin (Context ctx) id functions)))
-- | Update a 'Plugin' with a new 'Manifest'
-updateManifest :: Plugin -> Manifest -> Bool -> IO (Result ())
-updateManifest plugin manifest useWasi =
+updateManifest :: Plugin -> Manifest -> [Function] -> Bool -> IO (Result Plugin)
+updateManifest plugin manifest functions useWasi =
let wasm = toByteString $ toString manifest in
- update plugin wasm useWasi
+ update plugin wasm functions useWasi
-- | Check if a 'Plugin' is valid
isValid :: Plugin -> Bool
-isValid (Plugin _ p) = p >= 0
+isValid (Plugin _ p _) = p >= 0
-- | Set configuration values for a plugin
setConfig :: Plugin -> [(String, Maybe String)] -> IO Bool
-setConfig (Plugin (Context ctx) plugin) x =
+setConfig (Plugin (Context ctx) plugin _) x =
if plugin < 0
then return False
else
@@ -155,14 +187,14 @@ setLogFile filename level =
-- | Check if a function exists in the given plugin
functionExists :: Plugin -> String -> IO Bool
-functionExists (Plugin (Context ctx) plugin) name = do
+functionExists (Plugin (Context ctx) plugin _) name = do
withForeignPtr ctx (\ctx -> do
b <- withCString name (extism_plugin_function_exists ctx plugin)
if b == 1 then return True else return False)
--- | Call a function provided by the given plugin
call :: Plugin -> String -> B.ByteString -> IO (Result B.ByteString)
-call (Plugin (Context ctx) plugin) name input =
+call (Plugin (Context ctx) plugin _) name input =
let length = fromIntegral (B.length input) in
do
withForeignPtr ctx (\ctx -> do
@@ -184,15 +216,73 @@ call (Plugin (Context ctx) plugin) name input =
-- | Free a 'Plugin', this will automatically be called for every plugin
-- | associated with a 'Context' when that 'Context' is freed
free :: Plugin -> IO ()
-free (Plugin (Context ctx) plugin) =
+free (Plugin (Context ctx) plugin _) =
withForeignPtr ctx (`extism_plugin_free` plugin)
+-- | Create a new 'CancelHandle' that can be used to cancel a running plugin
+-- | from another thread.
cancelHandle :: Plugin -> IO CancelHandle
-cancelHandle (Plugin (Context ctx) plugin) = do
- handle <- withForeignPtr ctx (\ctx -> extism_plugin_cancel_handle ctx plugin)
+cancelHandle (Plugin (Context ctx) plugin _) = do
+ handle <- withForeignPtr ctx (`extism_plugin_cancel_handle` plugin)
return (CancelHandle handle)
+-- | Cancel a running plugin using a 'CancelHandle'
cancel :: CancelHandle -> IO Bool
-cancel (CancelHandle handle) =
+cancel (CancelHandle handle) =
extism_plugin_cancel handle
+
+-- | Create a new 'Function' that can be called from a 'Plugin'
+hostFunction :: String -> [ValType] -> [ValType] -> (CurrentPlugin -> [Val] -> a -> IO [Val]) -> a -> IO Function
+hostFunction name params results f v =
+ let nparams = fromIntegral $ Prelude.length params in
+ let nresults = fromIntegral $ Prelude.length results in
+ do
+ cb <- callbackWrap (callback f :: CCallback)
+ free <- freePtrWrap freePtr
+ userData <- newStablePtr (v, free, cb)
+ let userDataPtr = castStablePtrToPtr userData
+ x <- withCString name (\name -> do
+ withArray params (\params ->
+ withArray results (\results -> do
+ extism_function_new name params nparams results nresults cb userDataPtr free)))
+ let freeFn = extism_function_free x
+ fptr <- Foreign.Concurrent.newForeignPtr x freeFn
+ return $ Function fptr (castPtrToStablePtr userDataPtr)
+
+
+-- | Create a new I32 'Val'
+toI32 :: Integral a => a -> Val
+toI32 x = ValI32 (fromIntegral x)
+
+-- | Create a new I64 'Val'
+toI64 :: Integral a => a -> Val
+toI64 x = ValI64 (fromIntegral x)
+
+-- | Create a new F32 'Val'
+toF32 :: Float -> Val
+toF32 = ValF32
+
+-- | Create a new F64 'Val'
+toF64 :: Double -> Val
+toF64 = ValF64
+
+-- | Get I32 'Val'
+fromI32 :: Integral a => Val -> Maybe a
+fromI32 (ValI32 x) = Just (fromIntegral x)
+fromI32 _ = Nothing
+
+-- | Get I64 'Val'
+fromI64 :: Integral a => Val -> Maybe a
+fromI64 (ValI64 x) = Just (fromIntegral x)
+fromI64 _ = Nothing
+
+-- | Get F32 'Val'
+fromF32 :: Val -> Maybe Float
+fromF32 (ValF32 x) = Just x
+fromF32 _ = Nothing
+
+-- | Get F64 'Val'
+fromF64 :: Val -> Maybe Double
+fromF64 (ValF64 x) = Just x
+fromF64 _ = Nothing
\ No newline at end of file
diff --git a/haskell/src/Extism/Bindings.hs b/haskell/src/Extism/Bindings.hs
index fadebe113..2632934b7 100644
--- a/haskell/src/Extism/Bindings.hs
+++ b/haskell/src/Extism/Bindings.hs
@@ -7,10 +7,77 @@ import Foreign.Ptr
import Foreign.C.String
import Data.Int
import Data.Word
+import Foreign.Storable
+import Foreign.Marshal.Array
+import Foreign.StablePtr
+
+type FreeCallback = Ptr () -> IO ()
newtype ExtismContext = ExtismContext () deriving Show
newtype ExtismFunction = ExtismFunction () deriving Show
newtype ExtismCancelHandle = ExtismCancelHandle () deriving Show
+newtype ExtismCurrentPlugin = ExtismCurrentPlugin () deriving Show
+data ValType = I32 | I64 | F32 | F64 | V128 | FuncRef | ExternRef deriving (Show, Eq)
+data Val = ValI32 Int32 | ValI64 Int64 | ValF32 Float | ValF64 Double deriving (Show, Eq)
+
+typeOfVal (ValI32 _) = I32
+typeOfVal (ValI64 _) = I64
+typeOfVal (ValF32 _) = F32
+typeOfVal (ValF64 _) = F64
+
+type CCallback = Ptr ExtismCurrentPlugin -> Ptr Val -> Word64 -> Ptr Val -> Word64 -> Ptr () -> IO ()
+
+_32Bit = sizeOf (undefined :: Int) == 4
+
+instance Storable Val where
+ sizeOf _ =
+ if _32Bit then 12 else 16
+ alignment _ = 1
+ peek ptr = do
+ let offs = if _32Bit then 4 else 8
+ t <- valTypeOfInt <$> peekByteOff ptr 0
+ case t of
+ I32 -> ValI32 <$> peekByteOff ptr offs
+ I64 -> ValI64 <$> peekByteOff ptr offs
+ F32 -> ValF32 <$> peekByteOff ptr offs
+ F64 -> ValF64 <$> peekByteOff ptr offs
+ poke ptr x = do
+ let offs = if _32Bit then 4 else 8
+ pokeByteOff ptr 0 (typeOfVal x)
+ case x of
+ ValI32 x -> pokeByteOff ptr offs x
+ ValI64 x -> pokeByteOff ptr offs x
+ ValF32 x -> pokeByteOff ptr offs x
+ ValF64 x -> pokeByteOff ptr offs x
+
+
+intOfValType :: ValType -> CInt
+intOfValType I32 = 0
+intOfValType I64 = 1
+intOfValType F32 = 2
+intOfValType F64 = 3
+intOfValType V128 = 4
+intOfValType FuncRef = 5
+intOfValType ExternRef = 6
+
+valTypeOfInt :: CInt -> ValType
+valTypeOfInt 0 = I32
+valTypeOfInt 1 = I64
+valTypeOfInt 2 = F32
+valTypeOfInt 3 = F64
+valTypeOfInt 4 = V128
+valTypeOfInt 5 = FuncRef
+valTypeOfInt 6 = ExternRef
+valTypeOfInt _ = error "Invalid ValType"
+
+instance Storable ValType where
+ sizeOf _ = 4
+ alignment _ = 1
+ peek ptr = do
+ x <- peekByteOff ptr 0
+ return $ valTypeOfInt (x :: CInt)
+ poke ptr x = do
+ pokeByteOff ptr 0 (intOfValType x)
foreign import ccall safe "extism.h extism_context_new" extism_context_new :: IO (Ptr ExtismContext)
foreign import ccall safe "extism.h &extism_context_free" extism_context_free :: FunPtr (Ptr ExtismContext -> IO ())
@@ -28,3 +95,28 @@ foreign import ccall safe "extism.h extism_context_reset" extism_context_reset :
foreign import ccall safe "extism.h extism_version" extism_version :: IO CString
foreign import ccall safe "extism.h extism_plugin_cancel_handle" extism_plugin_cancel_handle :: Ptr ExtismContext -> Int32 -> IO (Ptr ExtismCancelHandle)
foreign import ccall safe "extism.h extism_plugin_cancel" extism_plugin_cancel :: Ptr ExtismCancelHandle -> IO Bool
+
+foreign import ccall safe "extism.h extism_function_new" extism_function_new :: CString -> Ptr ValType -> Word64 -> Ptr ValType -> Word64 -> FunPtr CCallback -> Ptr () -> FunPtr FreeCallback -> IO (Ptr ExtismFunction)
+foreign import ccall safe "extism.h extism_function_free" extism_function_free :: Ptr ExtismFunction -> IO ()
+foreign import ccall safe "extism.h extism_current_plugin_memory" extism_current_plugin_memory :: Ptr ExtismCurrentPlugin -> IO (Ptr Word8)
+foreign import ccall safe "extism.h extism_current_plugin_memory_alloc" extism_current_plugin_memory_alloc :: Ptr ExtismCurrentPlugin -> Word64 -> IO Word64
+foreign import ccall safe "extism.h extism_current_plugin_memory_length" extism_current_plugin_memory_length :: Ptr ExtismCurrentPlugin -> Word64 -> IO Word64
+foreign import ccall safe "extism.h extism_current_plugin_memory_free" extism_current_plugin_memory_free :: Ptr ExtismCurrentPlugin -> Word64 -> IO ()
+
+freePtr ptr = do
+ let s = castPtrToStablePtr ptr
+ (a, b, c) <- deRefStablePtr s
+ freeHaskellFunPtr b
+ freeHaskellFunPtr c
+ freeStablePtr s
+
+foreign import ccall "wrapper" freePtrWrap :: FreeCallback -> IO (FunPtr FreeCallback)
+
+foreign import ccall "wrapper" callbackWrap :: CCallback -> IO (FunPtr CCallback)
+
+callback :: (Ptr ExtismCurrentPlugin -> [Val] -> a -> IO [Val]) -> (Ptr ExtismCurrentPlugin -> Ptr Val -> Word64 -> Ptr Val -> Word64 -> Ptr () -> IO ())
+callback f plugin params nparams results nresults ptr = do
+ p <- peekArray (fromIntegral nparams) params
+ (userData, _, _) <- deRefStablePtr (castPtrToStablePtr ptr)
+ res <- f plugin p userData
+ pokeArray results res
diff --git a/haskell/src/Extism/CurrentPlugin.hs b/haskell/src/Extism/CurrentPlugin.hs
new file mode 100644
index 000000000..a9c4fc94c
--- /dev/null
+++ b/haskell/src/Extism/CurrentPlugin.hs
@@ -0,0 +1,48 @@
+module Extism.CurrentPlugin where
+
+import Extism
+import Extism.Bindings
+import Data.Word
+import Data.ByteString as B
+import Foreign.Ptr
+import Foreign.Marshal.Array
+
+-- | Allocate a new handle of the given size
+memoryAlloc :: CurrentPlugin -> Word64 -> IO Word64
+memoryAlloc = extism_current_plugin_memory_alloc
+
+-- | Get the length of a handle, returns 0 if the handle is invalid
+memoryLength :: CurrentPlugin -> Word64 -> IO Word64
+memoryLength = extism_current_plugin_memory_length
+
+-- | Free allocated memory
+memoryFree :: CurrentPlugin -> Word64 -> IO ()
+memoryFree = extism_current_plugin_memory_free
+
+-- | Access a pointer to the entire memory region
+memory :: CurrentPlugin -> IO (Ptr Word8)
+memory = extism_current_plugin_memory
+
+-- | Access a pointer the a specific offset in memory
+memoryOffset :: CurrentPlugin -> Word64 -> IO (Ptr Word8)
+memoryOffset plugin offs = do
+ x <- extism_current_plugin_memory plugin
+ return $ plusPtr x (fromIntegral offs)
+
+-- | Access the data associated with a handle as a 'ByteString'
+memoryBytes :: CurrentPlugin -> Word64 -> IO B.ByteString
+memoryBytes plugin offs = do
+ ptr <- memoryOffset plugin offs
+ len <- memoryLength plugin offs
+ arr <- peekArray (fromIntegral len) ptr
+ return $ B.pack arr
+
+-- | Allocate memory and copy an existing 'ByteString' into it
+allocBytes :: CurrentPlugin -> B.ByteString -> IO Word64
+allocBytes plugin s = do
+ let length = B.length s
+ offs <- memoryAlloc plugin (fromIntegral length)
+ ptr <- memoryOffset plugin offs
+ pokeArray ptr (B.unpack s)
+ return offs
+
diff --git a/haskell/test/Test.hs b/haskell/test/Test.hs
index 88190fbbf..eddddc96e 100644
--- a/haskell/test/Test.hs
+++ b/haskell/test/Test.hs
@@ -1,6 +1,7 @@
import Test.HUnit
import Extism
import Extism.Manifest
+import Extism.CurrentPlugin
unwrap (Right x) = return x
@@ -8,12 +9,13 @@ unwrap (Left (ExtismError msg)) =
assertFailure msg
defaultManifest = manifest [wasmFile "../../wasm/code.wasm"]
+hostFunctionManifest = manifest [wasmFile "../../wasm/code-functions.wasm"]
initPlugin :: Maybe Context -> IO Plugin
initPlugin Nothing =
- Extism.createPluginFromManifest defaultManifest False >>= unwrap
+ Extism.createPluginFromManifest defaultManifest [] False >>= unwrap
initPlugin (Just ctx) =
- Extism.pluginFromManifest ctx defaultManifest False >>= unwrap
+ Extism.pluginFromManifest ctx defaultManifest [] False >>= unwrap
pluginFunctionExists = do
p <- initPlugin Nothing
@@ -30,6 +32,17 @@ pluginCall = do
p <- initPlugin Nothing
checkCallResult p
+
+hello plugin params () = do
+ putStrLn "Hello from Haskell!"
+ offs <- allocBytes plugin (toByteString "{\"count\": 999}")
+ return [toI64 offs]
+
+pluginCallHostFunction = do
+ p <- Extism.createPluginFromManifest hostFunctionManifest [] False >>= unwrap
+ res <- call p "count_vowels" (toByteString "this is a test") >>= unwrap
+ assertEqual "count vowels output" "{\"count\": 999}" (fromByteString res)
+
pluginMultiple = do
withContext(\ctx -> do
p <- initPlugin (Just ctx)
@@ -42,7 +55,7 @@ pluginMultiple = do
pluginUpdate = do
withContext (\ctx -> do
p <- initPlugin (Just ctx)
- updateManifest p defaultManifest True >>= unwrap
+ updateManifest p defaultManifest [] True >>= unwrap
checkCallResult p)
pluginConfig = do
@@ -62,6 +75,7 @@ main = do
[
t "Plugin.FunctionExists" pluginFunctionExists
, t "Plugin.Call" pluginCall
+ , t "Plugin.CallHostFunction" pluginCallHostFunction
, t "Plugin.Multiple" pluginMultiple
, t "Plugin.Update" pluginUpdate
, t "Plugin.Config" pluginConfig
diff --git a/runtime/extism.h b/runtime/extism.h
index e7544e6f7..9df283f02 100644
--- a/runtime/extism.h
+++ b/runtime/extism.h
@@ -250,7 +250,7 @@ const char *extism_error(ExtismContext *ctx, ExtismPlugin plugin);
ExtismSize extism_plugin_output_length(ExtismContext *ctx, ExtismPlugin plugin);
/**
- * Get the length of a plugin's output data
+ * Get a pointer to the output data
*/
const uint8_t *extism_plugin_output_data(ExtismContext *ctx, ExtismPlugin plugin);
diff --git a/runtime/src/internal.rs b/runtime/src/internal.rs
index 84db6b2c4..a43dfe58d 100644
--- a/runtime/src/internal.rs
+++ b/runtime/src/internal.rs
@@ -83,6 +83,7 @@ pub trait InternalExt {
}
fn memory_read(&mut self, offs: u64, len: Size) -> &[u8] {
+ trace!("memory_read: {}, {}", offs, len);
let offs = offs as usize;
let len = len as usize;
let mem = self.memory();
@@ -95,6 +96,7 @@ pub trait InternalExt {
}
fn memory_write(&mut self, offs: u64, bytes: impl AsRef<[u8]>) {
+ trace!("memory_write: {}", offs);
let b = bytes.as_ref();
let offs = offs as usize;
let len = b.len();
@@ -114,6 +116,7 @@ pub trait InternalExt {
if offs == 0 {
anyhow::bail!("out of memory")
}
+ trace!("memory_alloc: {}, {}", offs, n);
Ok(offs)
}
@@ -145,7 +148,9 @@ pub trait InternalExt {
.unwrap()
.call(&mut store, &[Val::I64(offs as i64)], output)
.unwrap();
- output[0].unwrap_i64() as u64
+ let len = output[0].unwrap_i64() as u64;
+ trace!("memory_length: {}, {}", offs, len);
+ len
}
// A convenience method to set the plugin error and return a value
diff --git a/runtime/src/sdk.rs b/runtime/src/sdk.rs
index c26db7717..215dfbf6c 100644
--- a/runtime/src/sdk.rs
+++ b/runtime/src/sdk.rs
@@ -657,7 +657,7 @@ pub unsafe extern "C" fn extism_plugin_output_length(
len
}
-/// Get the length of a plugin's output data
+/// Get a pointer to the output data
#[no_mangle]
pub unsafe extern "C" fn extism_plugin_output_data(
ctx: *mut Context,
@@ -682,7 +682,10 @@ pub unsafe extern "C" fn extism_plugin_output_data(
.unwrap()
.call(&mut store, &[], out)
.unwrap();
- ptr.add(out[0].unwrap_i64() as usize)
+
+ let offs = out[0].unwrap_i64() as usize;
+ trace!("Output offset: {}", offs);
+ ptr.add(offs)
}
/// Set log file and level
From 3420960d7f4633109cbbb44b62f71b8155212039 Mon Sep 17 00:00:00 2001
From: zach
Date: Tue, 1 Aug 2023 10:28:53 -0700
Subject: [PATCH 012/176] chore(zig): use LazyPath in build.zig (#406)
---
zig/build.zig | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/zig/build.zig b/zig/build.zig
index b5160a449..26240b8d9 100644
--- a/zig/build.zig
+++ b/zig/build.zig
@@ -30,8 +30,8 @@ pub fn build(b: *std.Build) void {
tests.addAnonymousModule("extism", .{ .source_file = .{ .path = "src/main.zig" } });
tests.linkLibC();
- tests.addIncludePath("/usr/local/include");
- tests.addLibraryPath("/usr/local/lib");
+ tests.addIncludePath(.{ .path = "/usr/local/include" });
+ tests.addLibraryPath(.{ .path = "/usr/local/lib" });
tests.linkSystemLibrary("extism");
const tests_run_step = b.addRunArtifact(tests);
@@ -47,8 +47,8 @@ pub fn build(b: *std.Build) void {
example.addAnonymousModule("extism", .{ .source_file = .{ .path = "src/main.zig" } });
example.linkLibC();
- example.addIncludePath("/usr/local/include");
- example.addLibraryPath("/usr/local/lib");
+ example.addIncludePath(.{ .path = "/usr/local/include" });
+ example.addLibraryPath(.{ .path = "/usr/local/lib" });
example.linkSystemLibrary("extism");
const example_run_step = b.addRunArtifact(example);
From c7c7f9d0248642de1e9bbf256f8a2ae6f9ea18f7 Mon Sep 17 00:00:00 2001
From: zach
Date: Tue, 1 Aug 2023 11:12:02 -0700
Subject: [PATCH 013/176] chore: update wasmtime bounds to include 11.0 (#405)
---
runtime/Cargo.toml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 477811861..fd18b2bd8 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -9,9 +9,9 @@ repository = "https://github.com/extism/extism"
description = "Extism runtime component"
[dependencies]
-wasmtime = ">= 8.0.0, < 11.0.0"
-wasmtime-wasi = ">= 8.0.0, < 11.0.0"
-wasmtime-wasi-nn = {version = ">= 8.0.0, < 11.0.0", optional=true}
+wasmtime = ">= 8.0.0, < 12.0.0"
+wasmtime-wasi = ">= 8.0.0, < 12.0.0"
+wasmtime-wasi-nn = {version = ">= 8.0.0, < 12.0.0", optional=true}
anyhow = "1"
serde = {version = "1", features = ["derive"]}
serde_json = "1"
From 07623ef2daf39682a258de3b81a279a118fa6274 Mon Sep 17 00:00:00 2001
From: zach
Date: Fri, 4 Aug 2023 13:44:24 -0700
Subject: [PATCH 014/176] fix: avoid timeout errors outside of
`extism_plugin_call` (#407)
- Delays instantiation to right before a call by using `instantiate_pre`
instead. This fixes an issue with the assemblyscript PDK.
- Makes timeouts only apply to calls
- Also bumps the wasmtime lower-bounds to 10.0, because the return type
of the epoch callback has changed
---
runtime/Cargo.toml | 6 ++---
runtime/src/plugin.rs | 51 ++++++++++++++++++++++++---------------
runtime/src/plugin_ref.rs | 17 ++-----------
runtime/src/sdk.rs | 13 +++++++---
rust/src/lib.rs | 20 +++++++++++++++
5 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index fd18b2bd8..6deff2fa6 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -9,9 +9,9 @@ repository = "https://github.com/extism/extism"
description = "Extism runtime component"
[dependencies]
-wasmtime = ">= 8.0.0, < 12.0.0"
-wasmtime-wasi = ">= 8.0.0, < 12.0.0"
-wasmtime-wasi-nn = {version = ">= 8.0.0, < 12.0.0", optional=true}
+wasmtime = ">= 10.0.0, < 12.0.0"
+wasmtime-wasi = ">= 10.0.0, < 12.0.0"
+wasmtime-wasi-nn = {version = ">= 10.0.0, < 12.0.0", optional=true}
anyhow = "1"
serde = {version = "1", features = ["derive"]}
serde_json = "1"
diff --git a/runtime/src/plugin.rs b/runtime/src/plugin.rs
index b7e04ecf2..44d77b8de 100644
--- a/runtime/src/plugin.rs
+++ b/runtime/src/plugin.rs
@@ -12,7 +12,8 @@ pub struct Plugin {
pub store: Store,
/// Instance provides the ability to call functions in a module
- pub instance: Instance,
+ pub instance: Option,
+ pub instance_pre: InstancePre,
/// Keep track of the number of times we're instantiated, this exists
/// to avoid issues with memory piling up since `Instance`s are only
@@ -147,7 +148,7 @@ impl Plugin {
&engine,
Internal::new(manifest, with_wasi, available_pages)?,
);
- store.epoch_deadline_callback(|_internal| Err(Error::msg("timeout")));
+ store.epoch_deadline_callback(|_internal| Ok(wasmtime::UpdateDeadline::Continue(1)));
if available_pages.is_some() {
store.limiter(|internal| internal.memory_limiter.as_mut().unwrap());
@@ -222,12 +223,13 @@ impl Plugin {
}
}
- let instance = linker.instantiate(&mut store, main)?;
+ let instance_pre = linker.instantiate_pre(&main)?;
let timer_id = uuid::Uuid::new_v4();
let mut plugin = Plugin {
modules,
linker,
- instance,
+ instance: None,
+ instance_pre,
store,
instantiations: 1,
runtime: None,
@@ -240,24 +242,27 @@ impl Plugin {
plugin.internal_mut().store = &mut plugin.store;
plugin.internal_mut().linker = &mut plugin.linker;
-
- // Then detect runtime before returning the new plugin
- plugin.detect_runtime();
Ok(plugin)
}
/// Get a function by name
pub fn get_func(&mut self, function: impl AsRef) -> Option {
- self.instance.get_func(&mut self.store, function.as_ref())
+ if let None = &self.instance {
+ if let Ok(x) = self.instance_pre.instantiate(&mut self.store) {
+ self.instance = Some(x);
+ self.detect_runtime();
+ }
+ }
+
+ if let Some(instance) = &mut self.instance {
+ instance.get_func(&mut self.store, function.as_ref())
+ } else {
+ None
+ }
}
/// Store input in memory and initialize `Internal` pointer
- pub(crate) fn set_input(
- &mut self,
- input: *const u8,
- mut len: usize,
- tx: std::sync::mpsc::SyncSender,
- ) -> Result<(), Error> {
+ pub(crate) fn set_input(&mut self, input: *const u8, mut len: usize) -> Result<(), Error> {
if input.is_null() {
len = 0;
}
@@ -273,7 +278,6 @@ impl Plugin {
let bytes = unsafe { std::slice::from_raw_parts(input, len) };
trace!("Input size: {}", bytes.len());
- self.start_timer(&tx)?;
if let Some(f) = self.linker.get(&mut self.store, "env", "extism_reset") {
f.into_func().unwrap().call(&mut self.store, &[], &mut [])?;
}
@@ -318,7 +322,7 @@ impl Plugin {
)?,
);
self.store
- .epoch_deadline_callback(|_internal| Err(Error::msg("timeout")));
+ .epoch_deadline_callback(|_internal| Ok(UpdateDeadline::Continue(1)));
if self.internal().available_pages.is_some() {
self.store
@@ -331,11 +335,16 @@ impl Plugin {
}
}
self.instantiations = 0;
+ self.instance_pre = self.linker.instantiate_pre(&main)?;
+
+ let store = &mut self.store as *mut _;
+ let linker = &mut self.linker as *mut _;
+ let internal = self.internal_mut();
+ internal.store = store;
+ internal.linker = linker;
}
- let instance = self.linker.instantiate(&mut self.store, main)?;
- self.instance = instance;
- self.detect_runtime();
+ self.instance = None;
self.instantiations += 1;
Ok(())
}
@@ -477,6 +486,8 @@ impl Plugin {
.map(std::time::Duration::from_millis);
self.cancel_handle.epoch_timer_tx = Some(tx.clone());
self.store_mut().set_epoch_deadline(1);
+ self.store
+ .epoch_deadline_callback(|_internal| Err(Error::msg("timeout")));
let engine: Engine = self.store().engine().clone();
tx.send(TimerAction::Start {
id: self.timer_id,
@@ -491,6 +502,8 @@ impl Plugin {
if let Some(tx) = &self.cancel_handle.epoch_timer_tx {
tx.send(TimerAction::Stop { id: self.timer_id })?;
}
+ self.store
+ .epoch_deadline_callback(|_internal| Ok(wasmtime::UpdateDeadline::Continue(1)));
Ok(())
}
}
diff --git a/runtime/src/plugin_ref.rs b/runtime/src/plugin_ref.rs
index 5e6e67248..164d15168 100644
--- a/runtime/src/plugin_ref.rs
+++ b/runtime/src/plugin_ref.rs
@@ -41,26 +41,13 @@ impl<'a> PluginRef<'a> {
return ctx.error(format!("Plugin does not exist: {plugin_id}"), None);
};
- {
- let plugin = unsafe { &mut *plugin };
- // Start timer
- if let Err(e) = plugin.start_timer(&epoch_timer_tx) {
- let id = plugin.timer_id;
- plugin.error(
- format!("Unable to start timeout manager for {id}: {e:?}"),
- (),
- );
- return None;
- }
- }
+ let plugin = unsafe { &mut *plugin };
if clear_error {
trace!("Clearing context error");
ctx.error = None;
trace!("Clearing plugin error: {plugin_id}");
- unsafe {
- (*plugin).clear_error();
- }
+ plugin.clear_error();
}
Some(PluginRef {
diff --git a/runtime/src/sdk.rs b/runtime/src/sdk.rs
index 215dfbf6c..124fca5dc 100644
--- a/runtime/src/sdk.rs
+++ b/runtime/src/sdk.rs
@@ -526,6 +526,10 @@ pub unsafe extern "C" fn extism_plugin_call(
);
}
+ if let Err(e) = plugin.set_input(data, data_len as usize) {
+ return plugin.error(e, -1);
+ }
+
// Initialize runtime
if !is_start {
if let Err(e) = plugin.initialize_runtime() {
@@ -533,14 +537,15 @@ pub unsafe extern "C" fn extism_plugin_call(
}
}
- if let Err(e) = plugin.set_input(data, data_len as usize, tx) {
- return plugin.error(e, -1);
- }
-
if plugin.has_error() {
return -1;
}
+ // Start timer, this will be stopped when PluginRef goes out of scope
+ if let Err(e) = plugin.start_timer(&tx) {
+ return plugin.error(e, -1);
+ }
+
debug!("Calling function: {name} in plugin {plugin_id}");
// Call the function
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 0961938fe..8777d63da 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -283,4 +283,24 @@ mod tests {
println!("Cancelled plugin ran for {:?}", time);
// std::io::stdout().write_all(output).unwrap();
}
+
+ #[test]
+ fn test_multiple_instantiations() {
+ let f = Function::new(
+ "hello_world",
+ [ValType::I64],
+ [ValType::I64],
+ None,
+ hello_world,
+ );
+
+ let context = Context::new();
+ let mut plugin = Plugin::new(&context, WASM, [f], true).unwrap();
+
+ // This is 10,001 because the wasmtime store limit is 10,000 - we want to test
+ // that our reinstantiation process is working and that limit is never hit.
+ for _ in 0..10001 {
+ let _output = plugin.call("count_vowels", "abc123").unwrap();
+ }
+ }
}
From d80584600bde51f0673bf3752f94ef355cbc0fa0 Mon Sep 17 00:00:00 2001
From: zach
Date: Tue, 8 Aug 2023 14:12:09 -0700
Subject: [PATCH 015/176] refactor: Simplify runtime handling (#411)
It seems like our runtime initialization process is a little too
aggressive, this PR scales it back to initialize the runtime once if it
exists and only reinitializes when `_start` is called. This prevents
globals from being wiped out between plugin calls.
- Removes Runtime::cleanup
- Only initializes runtime once, or if `_start` is called
- Improves Haskell reactor support
See https://github.com/extism/go-sdk/pull/11 for the go-sdk PR.
---
haskell/extism.cabal | 6 +-
haskell/manifest/extism-manifest.cabal | 6 +-
runtime/src/plugin.rs | 249 +++++++++++--------------
runtime/src/plugin_ref.rs | 21 ++-
runtime/src/sdk.rs | 32 +---
rust/src/bindings.rs | 236 ++++++++++++++++++++++-
rust/src/lib.rs | 12 ++
wasm/globals.wasm | Bin 0 -> 18011 bytes
8 files changed, 381 insertions(+), 181 deletions(-)
create mode 100755 wasm/globals.wasm
diff --git a/haskell/extism.cabal b/haskell/extism.cabal
index 1a5d4c3c2..518c73a87 100644
--- a/haskell/extism.cabal
+++ b/haskell/extism.cabal
@@ -19,9 +19,9 @@ library
extra-libraries: extism
extra-lib-dirs: /usr/local/lib
build-depends:
- base >= 4.16.1 && < 4.19.0,
- bytestring >= 0.11.3 && < 0.12,
- json >= 0.10 && < 0.11,
+ base >= 4.16.1 && < 5,
+ bytestring >= 0.11.3 && <= 0.12,
+ json >= 0.10 && <= 0.11,
extism-manifest >= 0.0.0 && < 0.3.0
test-suite extism-example
diff --git a/haskell/manifest/extism-manifest.cabal b/haskell/manifest/extism-manifest.cabal
index 398d9bd53..941910b25 100644
--- a/haskell/manifest/extism-manifest.cabal
+++ b/haskell/manifest/extism-manifest.cabal
@@ -15,7 +15,7 @@ library
hs-source-dirs: .
default-language: Haskell2010
build-depends:
- base >= 4.16.1 && < 4.19.0,
- bytestring >= 0.11.3 && < 0.12,
- json >= 0.10 && < 0.11,
+ base >= 4.16.1 && < 5,
+ bytestring >= 0.11.3 && <= 0.12,
+ json >= 0.10 && <= 0.11,
base64-bytestring >= 1.2.1 && < 1.3,
diff --git a/runtime/src/plugin.rs b/runtime/src/plugin.rs
index 44d77b8de..01635919a 100644
--- a/runtime/src/plugin.rs
+++ b/runtime/src/plugin.rs
@@ -18,7 +18,7 @@ pub struct Plugin {
/// Keep track of the number of times we're instantiated, this exists
/// to avoid issues with memory piling up since `Instance`s are only
/// actually cleaned up along with a `Store`
- pub instantiations: usize,
+ instantiations: usize,
/// The ID used to identify this plugin with the `Timer`
pub timer_id: uuid::Uuid,
@@ -26,7 +26,7 @@ pub struct Plugin {
/// A handle used to cancel execution of a plugin
pub(crate) cancel_handle: sdk::ExtismCancelHandle,
- /// Runtime determines any initialization and cleanup functions needed
+ /// Runtime determines any initialization functions needed
/// to run a module
pub(crate) runtime: Option,
}
@@ -231,13 +231,13 @@ impl Plugin {
instance: None,
instance_pre,
store,
- instantiations: 1,
runtime: None,
timer_id,
cancel_handle: sdk::ExtismCancelHandle {
id: timer_id,
epoch_timer_tx: None,
},
+ instantiations: 0,
};
plugin.internal_mut().store = &mut plugin.store;
@@ -245,12 +245,71 @@ impl Plugin {
Ok(plugin)
}
+ pub(crate) fn reset_store(&mut self) -> Result<(), Error> {
+ self.instance = None;
+ if self.instantiations > 5 {
+ let (main_name, main) = self
+ .modules
+ .get("main")
+ .map(|x| ("main", x))
+ .unwrap_or_else(|| {
+ let entry = self.modules.iter().last().unwrap();
+ (entry.0.as_str(), entry.1)
+ });
+
+ let engine = self.store.engine().clone();
+ let internal = self.internal();
+ self.store = Store::new(
+ &engine,
+ Internal::new(
+ internal.manifest.clone(),
+ internal.wasi.is_some(),
+ internal.available_pages,
+ )?,
+ );
+ self.store
+ .epoch_deadline_callback(|_internal| Ok(UpdateDeadline::Continue(1)));
+
+ if self.internal().available_pages.is_some() {
+ self.store
+ .limiter(|internal| internal.memory_limiter.as_mut().unwrap());
+ }
+
+ for (name, module) in self.modules.iter() {
+ if name != main_name {
+ self.linker.module(&mut self.store, name, module)?;
+ }
+ }
+ self.instantiations = 0;
+ self.instance_pre = self.linker.instantiate_pre(&main)?;
+
+ let store = &mut self.store as *mut _;
+ let linker = &mut self.linker as *mut _;
+ let internal = self.internal_mut();
+ internal.store = store;
+ internal.linker = linker;
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn instantiate(&mut self) -> Result<(), Error> {
+ self.instance = Some(self.instance_pre.instantiate(&mut self.store)?);
+ self.instantiations += 1;
+ if let Some(limiter) = &mut self.internal_mut().memory_limiter {
+ limiter.reset();
+ }
+ self.detect_runtime();
+ self.initialize_runtime()?;
+ Ok(())
+ }
+
/// Get a function by name
pub fn get_func(&mut self, function: impl AsRef) -> Option {
if let None = &self.instance {
- if let Ok(x) = self.instance_pre.instantiate(&mut self.store) {
- self.instance = Some(x);
- self.detect_runtime();
+ if let Err(e) = self.instantiate() {
+ error!("Unable to instantiate: {e}");
+ return None;
}
}
@@ -280,6 +339,8 @@ impl Plugin {
if let Some(f) = self.linker.get(&mut self.store, "env", "extism_reset") {
f.into_func().unwrap().call(&mut self.store, &[], &mut [])?;
+ } else {
+ error!("Call to extism_reset failed");
}
let offs = self.memory_alloc_bytes(bytes)?;
@@ -295,60 +356,6 @@ impl Plugin {
Ok(())
}
- /// Create a new instance from the same modules
- pub fn reinstantiate(&mut self) -> Result<(), Error> {
- if let Some(limiter) = self.internal_mut().memory_limiter.as_mut() {
- limiter.reset();
- }
-
- let (main_name, main) = self
- .modules
- .get("main")
- .map(|x| ("main", x))
- .unwrap_or_else(|| {
- let entry = self.modules.iter().last().unwrap();
- (entry.0.as_str(), entry.1)
- });
-
- if self.instantiations > 5 {
- let engine = self.store.engine().clone();
- let internal = self.internal();
- self.store = Store::new(
- &engine,
- Internal::new(
- internal.manifest.clone(),
- internal.wasi.is_some(),
- internal.available_pages,
- )?,
- );
- self.store
- .epoch_deadline_callback(|_internal| Ok(UpdateDeadline::Continue(1)));
-
- if self.internal().available_pages.is_some() {
- self.store
- .limiter(|internal| internal.memory_limiter.as_mut().unwrap());
- }
-
- for (name, module) in self.modules.iter() {
- if name != main_name {
- self.linker.module(&mut self.store, name, module)?;
- }
- }
- self.instantiations = 0;
- self.instance_pre = self.linker.instantiate_pre(&main)?;
-
- let store = &mut self.store as *mut _;
- let linker = &mut self.linker as *mut _;
- let internal = self.internal_mut();
- internal.store = store;
- internal.linker = linker;
- }
-
- self.instance = None;
- self.instantiations += 1;
- Ok(())
- }
-
/// Determine if wasi is enabled
pub fn has_wasi(&self) -> bool {
self.internal().wasi.is_some()
@@ -356,66 +363,55 @@ impl Plugin {
fn detect_runtime(&mut self) {
// Check for Haskell runtime initialization functions
- // Initialize Haskell runtime if `hs_init` and `hs_exit` are present,
+ // Initialize Haskell runtime if `hs_init` is present,
// by calling the `hs_init` export
if let Some(init) = self.get_func("hs_init") {
- if let Some(cleanup) = self.get_func("hs_exit") {
- if init.typed::<(i32, i32), ()>(&self.store()).is_err() {
- trace!(
- "hs_init function found with type {:?}",
- init.ty(self.store())
- );
- }
- self.runtime = Some(Runtime::Haskell { init, cleanup });
- }
- return;
- }
-
- // Check for `__wasm_call_ctors` and `__wasm_call_dtors`, this is used by WASI to
- // initialize certain interfaces.
- if self.has_wasi() {
- let init = if let Some(init) = self.get_func("__wasm_call_ctors") {
- if init.typed::<(), ()>(&self.store()).is_err() {
- trace!(
- "__wasm_call_ctors function found with type {:?}",
- init.ty(self.store())
- );
- return;
- }
- trace!("WASI runtime detected");
- init
- } else if let Some(init) = self.get_func("_initialize") {
+ let reactor_init = if let Some(init) = self.get_func("_initialize") {
if init.typed::<(), ()>(&self.store()).is_err() {
trace!(
"_initialize function found with type {:?}",
init.ty(self.store())
);
- return;
- }
- trace!("WASI reactor module detected");
- init
- } else {
- return;
- };
-
- let cleanup = if let Some(cleanup) = self.get_func("__wasm_call_dtors") {
- if cleanup.typed::<(), ()>(&self.store()).is_err() {
- trace!(
- "__wasm_call_dtors function found with type {:?}",
- cleanup.ty(self.store())
- );
None
} else {
- Some(cleanup)
+ trace!("WASI reactor module detected");
+ Some(init)
}
} else {
None
};
-
- self.runtime = Some(Runtime::Wasi { init, cleanup });
+ self.runtime = Some(Runtime::Haskell { init, reactor_init });
return;
}
+ // Check for `__wasm_call_ctors` or `_initialize`, this is used by WASI to
+ // initialize certain interfaces.
+ let init = if let Some(init) = self.get_func("__wasm_call_ctors") {
+ if init.typed::<(), ()>(&self.store()).is_err() {
+ trace!(
+ "__wasm_call_ctors function found with type {:?}",
+ init.ty(self.store())
+ );
+ return;
+ }
+ trace!("WASI runtime detected");
+ init
+ } else if let Some(init) = self.get_func("_initialize") {
+ if init.typed::<(), ()>(&self.store()).is_err() {
+ trace!(
+ "_initialize function found with type {:?}",
+ init.ty(self.store())
+ );
+ return;
+ }
+ trace!("Reactor module detected");
+ init
+ } else {
+ return;
+ };
+
+ self.runtime = Some(Runtime::Wasi { init });
+
trace!("No runtime detected");
}
@@ -424,7 +420,10 @@ impl Plugin {
if let Some(runtime) = &self.runtime {
trace!("Plugin::initialize_runtime");
match runtime {
- Runtime::Haskell { init, cleanup: _ } => {
+ Runtime::Haskell { init, reactor_init } => {
+ if let Some(reactor_init) = reactor_init {
+ reactor_init.call(&mut store, &[], &mut [])?;
+ }
let mut results = vec![Val::null(); init.ty(&store).results().len()];
init.call(
&mut store,
@@ -433,7 +432,7 @@ impl Plugin {
)?;
debug!("Initialized Haskell language runtime");
}
- Runtime::Wasi { init, cleanup: _ } => {
+ Runtime::Wasi { init } => {
init.call(&mut store, &[], &mut [])?;
debug!("Initialied WASI runtime");
}
@@ -443,35 +442,6 @@ impl Plugin {
Ok(())
}
- #[inline(always)]
- pub(crate) fn cleanup_runtime(&mut self) -> Result<(), Error> {
- if let Some(runtime) = self.runtime.clone() {
- trace!("Plugin::cleanup_runtime");
- match runtime {
- Runtime::Wasi {
- init: _,
- cleanup: Some(cleanup),
- } => {
- debug!("Calling __wasm_call_dtors");
- cleanup.call(self.store_mut(), &[], &mut [])?;
- }
- Runtime::Wasi {
- init: _,
- cleanup: None,
- } => (),
- // Cleanup Haskell runtime if `hs_exit` and `hs_exit` are present,
- // by calling the `hs_exit` export
- Runtime::Haskell { init: _, cleanup } => {
- let mut results = vec![Val::null(); cleanup.ty(self.store()).results().len()];
- cleanup.call(self.store_mut(), &[], results.as_mut_slice())?;
- debug!("Cleaned up Haskell language runtime");
- }
- }
- }
-
- Ok(())
- }
-
/// Start the timer for a Plugin - this is used for both timeouts
/// and cancellation
pub(crate) fn start_timer(
@@ -511,6 +481,11 @@ impl Plugin {
// Enumerates the supported PDK language runtimes
#[derive(Clone)]
pub(crate) enum Runtime {
- Haskell { init: Func, cleanup: Func },
- Wasi { init: Func, cleanup: Option },
+ Haskell {
+ init: Func,
+ reactor_init: Option,
+ },
+ Wasi {
+ init: Func,
+ },
}
diff --git a/runtime/src/plugin_ref.rs b/runtime/src/plugin_ref.rs
index 164d15168..de5c114fc 100644
--- a/runtime/src/plugin_ref.rs
+++ b/runtime/src/plugin_ref.rs
@@ -11,17 +11,24 @@ pub struct PluginRef<'a> {
impl<'a> PluginRef<'a> {
/// Initialize the plugin for a new call
- pub fn start_call(mut self) -> Self {
+ pub(crate) fn start_call(mut self, is_start: bool) -> Self {
trace!("PluginRef::start_call: {}", self.id,);
- let plugin = self.as_mut();
- if plugin.has_wasi() || plugin.runtime.is_some() {
- if let Err(e) = plugin.reinstantiate() {
- error!("Failed to reinstantiate: {e:?}");
- plugin.error(format!("Failed to reinstantiate: {e:?}"), ());
- return self;
+ let plugin = unsafe { &mut *self.plugin };
+ if is_start {
+ if let Err(e) = plugin.reset_store() {
+ error!("Call to Plugin::reset_store failed: {e:?}");
}
}
+
+ if plugin.instance.is_none() {
+ trace!("Plugin::instance is none, instantiating");
+ if let Err(e) = plugin.instantiate() {
+ error!("Plugin::instantiate failed: {e:?}");
+ plugin.error(e, ());
+ }
+ }
+
self.running = true;
self
}
diff --git a/runtime/src/sdk.rs b/runtime/src/sdk.rs
index 124fca5dc..f686a8734 100644
--- a/runtime/src/sdk.rs
+++ b/runtime/src/sdk.rs
@@ -495,23 +495,23 @@ pub unsafe extern "C" fn extism_plugin_call(
) -> i32 {
let ctx = &mut *ctx;
+ // Get function name
+ let name = std::ffi::CStr::from_ptr(func_name);
+ let name = match name.to_str() {
+ Ok(name) => name,
+ Err(e) => return ctx.error(e, -1),
+ };
+ let is_start = name == "_start";
+
// Get a `PluginRef` and call `init` to set up the plugin input and memory, this is only
// needed before a new call
let mut plugin_ref = match PluginRef::new(ctx, plugin_id, true) {
None => return -1,
- Some(p) => p.start_call(),
+ Some(p) => p.start_call(is_start),
};
let tx = plugin_ref.epoch_timer_tx.clone();
let plugin = plugin_ref.as_mut();
- // Find function
- let name = std::ffi::CStr::from_ptr(func_name);
- let name = match name.to_str() {
- Ok(name) => name,
- Err(e) => return plugin.error(e, -1),
- };
- let is_start = name == "_start";
-
let func = match plugin.get_func(name) {
Some(x) => x,
None => return plugin.error(format!("Function not found: {name}"), -1),
@@ -530,13 +530,6 @@ pub unsafe extern "C" fn extism_plugin_call(
return plugin.error(e, -1);
}
- // Initialize runtime
- if !is_start {
- if let Err(e) = plugin.initialize_runtime() {
- return plugin.error(format!("Failed to initialize runtime: {e:?}"), -1);
- }
- }
-
if plugin.has_error() {
return -1;
}
@@ -552,13 +545,6 @@ pub unsafe extern "C" fn extism_plugin_call(
let mut results = vec![wasmtime::Val::null(); n_results];
let res = func.call(plugin.store_mut(), &[], results.as_mut_slice());
- // Cleanup runtime
- if !is_start {
- if let Err(e) = plugin.cleanup_runtime() {
- return plugin.error(format!("Failed to cleanup runtime: {e:?}"), -1);
- }
- }
-
match res {
Ok(()) => (),
Err(e) => {
diff --git a/rust/src/bindings.rs b/rust/src/bindings.rs
index 71d8f589c..c1e136d24 100644
--- a/rust/src/bindings.rs
+++ b/rust/src/bindings.rs
@@ -1,45 +1,260 @@
-/* automatically generated by rust-bindgen 0.60.1 */
+/* automatically generated by rust-bindgen 0.65.1 */
-pub type __uint8_t = ::std::os::raw::c_uchar;
-pub type __int32_t = ::std::os::raw::c_int;
-pub type __uint64_t = ::std::os::raw::c_ulong;
+#[doc = " Signed 32 bit integer."]
+pub const ExtismValType_I32: ExtismValType = 0;
+#[doc = " Signed 64 bit integer."]
+pub const ExtismValType_I64: ExtismValType = 1;
+#[doc = " Floating point 32 bit integer."]
+pub const ExtismValType_F32: ExtismValType = 2;
+#[doc = " Floating point 64 bit integer."]
+pub const ExtismValType_F64: ExtismValType = 3;
+#[doc = " A 128 bit number."]
+pub const ExtismValType_V128: ExtismValType = 4;
+#[doc = " A reference to a Wasm function."]
+pub const ExtismValType_FuncRef: ExtismValType = 5;
+#[doc = " A reference to opaque data in the Wasm instance."]
+pub const ExtismValType_ExternRef: ExtismValType = 6;
+#[doc = " A list of all possible value types in WebAssembly."]
+pub type ExtismValType = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExtismContext {
_unused: [u8; 0],
}
-pub type ExtismPlugin = i32;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct ExtismCancelHandle {
+ _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct ExtismFunction {
+ _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct ExtismCurrentPlugin {
+ _unused: [u8; 0],
+}
pub type ExtismSize = u64;
+#[doc = " A union type for host function argument/return values"]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union ExtismValUnion {
+ pub i32_: i32,
+ pub i64_: i64,
+ pub f32_: f32,
+ pub f64_: f64,
+}
+#[test]
+fn bindgen_test_layout_ExtismValUnion() {
+ const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 8usize,
+ concat!("Size of: ", stringify!(ExtismValUnion))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(ExtismValUnion))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).i32_) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismValUnion),
+ "::",
+ stringify!(i32_)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).i64_) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismValUnion),
+ "::",
+ stringify!(i64_)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).f32_) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismValUnion),
+ "::",
+ stringify!(f32_)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).f64_) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismValUnion),
+ "::",
+ stringify!(f64_)
+ )
+ );
+}
+#[doc = " `ExtismVal` holds the type and value of a function argument/return"]
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct ExtismVal {
+ pub t: ExtismValType,
+ pub v: ExtismValUnion,
+}
+#[test]
+fn bindgen_test_layout_ExtismVal() {
+ const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::(),
+ 16usize,
+ concat!("Size of: ", stringify!(ExtismVal))
+ );
+ assert_eq!(
+ ::std::mem::align_of::(),
+ 8usize,
+ concat!("Alignment of ", stringify!(ExtismVal))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).t) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismVal),
+ "::",
+ stringify!(t)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ExtismVal),
+ "::",
+ stringify!(v)
+ )
+ );
+}
+#[doc = " Host function signature"]
+pub type ExtismFunctionType = ::std::option::Option<
+ unsafe extern "C" fn(
+ plugin: *mut ExtismCurrentPlugin,
+ inputs: *const ExtismVal,
+ n_inputs: ExtismSize,
+ outputs: *mut ExtismVal,
+ n_outputs: ExtismSize,
+ data: *mut ::std::os::raw::c_void,
+ ),
+>;
+pub type ExtismPlugin = i32;
extern "C" {
+ #[doc = " Create a new context"]
pub fn extism_context_new() -> *mut ExtismContext;
}
extern "C" {
+ #[doc = " Free a context"]
pub fn extism_context_free(ctx: *mut ExtismContext);
}
extern "C" {
+ #[doc = " Returns a pointer to the memory of the currently running plugin\n NOTE: this should only be called from host functions."]
+ pub fn extism_current_plugin_memory(plugin: *mut ExtismCurrentPlugin) -> *mut u8;
+}
+extern "C" {
+ #[doc = " Allocate a memory block in the currently running plugin\n NOTE: this should only be called from host functions."]
+ pub fn extism_current_plugin_memory_alloc(
+ plugin: *mut ExtismCurrentPlugin,
+ n: ExtismSize,
+ ) -> u64;
+}
+extern "C" {
+ #[doc = " Get the length of an allocated block\n NOTE: this should only be called from host functions."]
+ pub fn extism_current_plugin_memory_length(
+ plugin: *mut ExtismCurrentPlugin,
+ n: ExtismSize,
+ ) -> ExtismSize;
+}
+extern "C" {
+ #[doc = " Free an allocated memory block\n NOTE: this should only be called from host functions."]
+ pub fn extism_current_plugin_memory_free(plugin: *mut ExtismCurrentPlugin, ptr: u64);
+}
+extern "C" {
+ #[doc = " Create a new host function\n\n Arguments\n - `name`: function name, this should be valid UTF-8\n - `inputs`: argument types\n - `n_inputs`: number of argument types\n - `outputs`: return types\n - `n_outputs`: number of return types\n - `func`: the function to call\n - `user_data`: a pointer that will be passed to the function when it's called\n this value should live as long as the function exists\n - `free_user_data`: a callback to release the `user_data` value when the resulting\n `ExtismFunction` is freed.\n\n Returns a new `ExtismFunction` or `null` if the `name` argument is invalid."]
+ pub fn extism_function_new(
+ name: *const ::std::os::raw::c_char,
+ inputs: *const ExtismValType,
+ n_inputs: ExtismSize,
+ outputs: *const ExtismValType,
+ n_outputs: ExtismSize,
+ func: ExtismFunctionType,
+ user_data: *mut ::std::os::raw::c_void,
+ free_user_data: ::std::option::Option<
+ unsafe extern "C" fn(__: *mut ::std::os::raw::c_void),
+ >,
+ ) -> *mut ExtismFunction;
+}
+extern "C" {
+ #[doc = " Set the namespace of an `ExtismFunction`"]
+ pub fn extism_function_set_namespace(
+ ptr: *mut ExtismFunction,
+ namespace_: *const ::std::os::raw::c_char,
+ );
+}
+extern "C" {
+ #[doc = " Free an `ExtismFunction`"]
+ pub fn extism_function_free(ptr: *mut ExtismFunction);
+}
+extern "C" {
+ #[doc = " Create a new plugin with additional host functions\n\n `wasm`: is a WASM module (wat or wasm) or a JSON encoded manifest\n `wasm_size`: the length of the `wasm` parameter\n `functions`: an array of `ExtismFunction*`\n `n_functions`: the number of functions provided\n `with_wasi`: enables/disables WASI"]
pub fn extism_plugin_new(
ctx: *mut ExtismContext,
wasm: *const u8,
wasm_size: ExtismSize,
+ functions: *mut *const ExtismFunction,
+ n_functions: ExtismSize,
with_wasi: bool,
) -> ExtismPlugin;
}
extern "C" {
+ #[doc = " Update a plugin, keeping the existing ID\n\n Similar to `extism_plugin_new` but takes an `index` argument to specify\n which plugin to update\n\n Memory for this plugin will be reset upon update"]
pub fn extism_plugin_update(
ctx: *mut ExtismContext,
index: ExtismPlugin,
wasm: *const u8,
wasm_size: ExtismSize,
+ functions: *mut *const ExtismFunction,
+ nfunctions: ExtismSize,
with_wasi: bool,
) -> bool;
}
extern "C" {
+ #[doc = " Remove a plugin from the registry and free associated memory"]
pub fn extism_plugin_free(ctx: *mut ExtismContext, plugin: ExtismPlugin);
}
extern "C" {
+ #[doc = " Get plugin ID for cancellation"]
+ pub fn extism_plugin_cancel_handle(
+ ctx: *mut ExtismContext,
+ plugin: ExtismPlugin,
+ ) -> *const ExtismCancelHandle;
+}
+extern "C" {
+ #[doc = " Cancel a running plugin"]
+ pub fn extism_plugin_cancel(handle: *const ExtismCancelHandle) -> bool;
+}
+extern "C" {
+ #[doc = " Remove all plugins from the registry"]
pub fn extism_context_reset(ctx: *mut ExtismContext);
}
extern "C" {
+ #[doc = " Update plugin config values, this will merge with the existing values"]
pub fn extism_plugin_config(
ctx: *mut ExtismContext,
plugin: ExtismPlugin,
@@ -48,6 +263,7 @@ extern "C" {
) -> bool;
}
extern "C" {
+ #[doc = " Returns true if `func_name` exists"]
pub fn extism_plugin_function_exists(
ctx: *mut ExtismContext,
plugin: ExtismPlugin,
@@ -55,6 +271,7 @@ extern "C" {
) -> bool;
}
extern "C" {
+ #[doc = " Call a function\n\n `func_name`: is the function to call\n `data`: is the input data\n `data_len`: is the length of `data`"]
pub fn extism_plugin_call(
ctx: *mut ExtismContext,
plugin_id: ExtismPlugin,
@@ -64,26 +281,29 @@ extern "C" {
) -> i32;
}
extern "C" {
+ #[doc = " Get the error associated with a `Context` or `Plugin`, if `plugin` is `-1` then the context\n error will be returned"]
pub fn extism_error(
ctx: *mut ExtismContext,
plugin: ExtismPlugin,
) -> *const ::std::os::raw::c_char;
}
extern "C" {
+ #[doc = " Get the length of a plugin's output data"]
pub fn extism_plugin_output_length(ctx: *mut ExtismContext, plugin: ExtismPlugin)
-> ExtismSize;
}
extern "C" {
+ #[doc = " Get a pointer to the output data"]
pub fn extism_plugin_output_data(ctx: *mut ExtismContext, plugin: ExtismPlugin) -> *const u8;
}
extern "C" {
+ #[doc = " Set log file and level"]
pub fn extism_log_file(
filename: *const ::std::os::raw::c_char,
log_level: *const ::std::os::raw::c_char,
) -> bool;
}
-
extern "C" {
- pub fn extism_version(
- ) -> *const ::std::os::raw::c_char;
+ #[doc = " Get the Extism version string"]
+ pub fn extism_version() -> *const ::std::os::raw::c_char;
}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 8777d63da..ea9b3ddab 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -44,6 +44,7 @@ mod tests {
const WASM: &[u8] = include_bytes!("../../wasm/code-functions.wasm");
const WASM_LOOP: &[u8] = include_bytes!("../../wasm/loop.wasm");
+ const WASM_GLOBALS: &[u8] = include_bytes!("../../wasm/globals.wasm");
fn hello_world(
_plugin: &mut CurrentPlugin,
@@ -303,4 +304,15 @@ mod tests {
let _output = plugin.call("count_vowels", "abc123").unwrap();
}
}
+
+ #[test]
+ fn test_globals() {
+ let context = Context::new();
+ let mut plugin = Plugin::new(&context, WASM_GLOBALS, [], true).unwrap();
+ for i in 0..1000 {
+ let output = plugin.call("globals", "").unwrap();
+ let count: serde_json::Value = serde_json::from_slice(&output).unwrap();
+ assert_eq!(count.get("count").unwrap().as_i64().unwrap(), i);
+ }
+ }
}
diff --git a/wasm/globals.wasm b/wasm/globals.wasm
new file mode 100755
index 0000000000000000000000000000000000000000..8474a40d07ff6847dae60a5d20dc2f160a3410d9
GIT binary patch
literal 18011
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