nscript: load script view
This allows you to open and run scripts for testing purposes, but only from external links such as nostr:nscript...
This commit is contained in:
@@ -753,15 +753,6 @@ static char *instr_name(enum instr_tag tag)
|
|||||||
return unk;
|
return unk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int was_section_parsed(struct module *module,
|
|
||||||
enum section_tag section)
|
|
||||||
{
|
|
||||||
if (section == section_custom)
|
|
||||||
return module->custom_sections > 0;
|
|
||||||
|
|
||||||
return module->parsed & (1 << section);
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE int was_name_section_parsed(struct module *module,
|
static INLINE int was_name_section_parsed(struct module *module,
|
||||||
enum name_subsection_tag subsection)
|
enum name_subsection_tag subsection)
|
||||||
{
|
{
|
||||||
@@ -1322,7 +1313,7 @@ static int parse_valtype(struct wasm_parser *p, enum valtype *valtype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!is_valtype((unsigned char)*valtype))) {
|
if (unlikely(!is_valtype((unsigned char)*valtype))) {
|
||||||
cursor_print_around(&p->cur, 10);
|
//cursor_print_around(&p->cur, 10);
|
||||||
p->cur.p = start;
|
p->cur.p = start;
|
||||||
return parse_err(p, "0x%02x is not a valid valtype tag", *valtype);
|
return parse_err(p, "0x%02x is not a valid valtype tag", *valtype);
|
||||||
}
|
}
|
||||||
@@ -1684,7 +1675,7 @@ static int parse_reftype(struct wasm_parser *p, enum reftype *reftype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_valid_reftype(tag)) {
|
if (!is_valid_reftype(tag)) {
|
||||||
cursor_print_around(&p->cur, 10);
|
//cursor_print_around(&p->cur, 10);
|
||||||
parse_err(p, "invalid reftype: 0x%02x", tag);
|
parse_err(p, "invalid reftype: 0x%02x", tag);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2176,6 +2167,7 @@ static int parse_const_expr(struct expr_parser *p, struct expr *expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!is_const_instr(tag))) {
|
if (unlikely(!is_const_instr(tag))) {
|
||||||
|
//cursor_print_around(p->code, 20);
|
||||||
return note_error(p->errs, p->code,
|
return note_error(p->errs, p->code,
|
||||||
"invalid const expr instruction: '%s'",
|
"invalid const expr instruction: '%s'",
|
||||||
instr_name(tag));
|
instr_name(tag));
|
||||||
@@ -2551,7 +2543,7 @@ static int parse_wdata(struct wasm_parser *p, struct wdata *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tag > 2) {
|
if (tag > 2) {
|
||||||
cursor_print_around(&p->cur, 10);
|
//cursor_print_around(&p->cur, 10);
|
||||||
return parse_err(p, "invalid datasegment tag: 0x%x", tag);
|
return parse_err(p, "invalid datasegment tag: 0x%x", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -837,4 +837,14 @@ static INLINE struct callframe *top_callframes(struct cursor *cur, int top)
|
|||||||
return (struct callframe*)cursor_topn(cur, sizeof(struct callframe), top);
|
return (struct callframe*)cursor_topn(cur, sizeof(struct callframe), top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INLINE int was_section_parsed(struct module *module,
|
||||||
|
enum section_tag section)
|
||||||
|
{
|
||||||
|
if (section == section_custom)
|
||||||
|
return module->custom_sections > 0;
|
||||||
|
|
||||||
|
return module->parsed & (1 << section);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* PROTOVERSE_WASM_H */
|
#endif /* PROTOVERSE_WASM_H */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F92280F66F5000448DE /* ReplyMap.swift */; };
|
4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F92280F66F5000448DE /* ReplyMap.swift */; };
|
||||||
4C190F202A535FC200027FD5 /* CustomizeZapModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C190F1F2A535FC200027FD5 /* CustomizeZapModel.swift */; };
|
4C190F202A535FC200027FD5 /* CustomizeZapModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C190F1F2A535FC200027FD5 /* CustomizeZapModel.swift */; };
|
||||||
4C190F222A53950D00027FD5 /* bool_setting.wasm in Resources */ = {isa = PBXBuildFile; fileRef = 4C190F212A53950D00027FD5 /* bool_setting.wasm */; };
|
4C190F222A53950D00027FD5 /* bool_setting.wasm in Resources */ = {isa = PBXBuildFile; fileRef = 4C190F212A53950D00027FD5 /* bool_setting.wasm */; };
|
||||||
|
4C190F252A547D2000027FD5 /* LoadScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C190F242A547D2000027FD5 /* LoadScript.swift */; };
|
||||||
4C198DEF29F88C6B004C165C /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C198DEB29F88C6B004C165C /* BlurHashEncode.swift */; };
|
4C198DEF29F88C6B004C165C /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C198DEB29F88C6B004C165C /* BlurHashEncode.swift */; };
|
||||||
4C198DF029F88C6B004C165C /* Readme.md in Resources */ = {isa = PBXBuildFile; fileRef = 4C198DEC29F88C6B004C165C /* Readme.md */; };
|
4C198DF029F88C6B004C165C /* Readme.md in Resources */ = {isa = PBXBuildFile; fileRef = 4C198DEC29F88C6B004C165C /* Readme.md */; };
|
||||||
4C198DF129F88C6B004C165C /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4C198DED29F88C6B004C165C /* License.txt */; };
|
4C198DF129F88C6B004C165C /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4C198DED29F88C6B004C165C /* License.txt */; };
|
||||||
@@ -470,6 +471,7 @@
|
|||||||
4C0A3F92280F66F5000448DE /* ReplyMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyMap.swift; sourceTree = "<group>"; };
|
4C0A3F92280F66F5000448DE /* ReplyMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyMap.swift; sourceTree = "<group>"; };
|
||||||
4C190F1F2A535FC200027FD5 /* CustomizeZapModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizeZapModel.swift; sourceTree = "<group>"; };
|
4C190F1F2A535FC200027FD5 /* CustomizeZapModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizeZapModel.swift; sourceTree = "<group>"; };
|
||||||
4C190F212A53950D00027FD5 /* bool_setting.wasm */ = {isa = PBXFileReference; lastKnownFileType = file; name = bool_setting.wasm; path = nostrscript/bool_setting.wasm; sourceTree = SOURCE_ROOT; };
|
4C190F212A53950D00027FD5 /* bool_setting.wasm */ = {isa = PBXFileReference; lastKnownFileType = file; name = bool_setting.wasm; path = nostrscript/bool_setting.wasm; sourceTree = SOURCE_ROOT; };
|
||||||
|
4C190F242A547D2000027FD5 /* LoadScript.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadScript.swift; sourceTree = "<group>"; };
|
||||||
4C198DEB29F88C6B004C165C /* BlurHashEncode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = "<group>"; };
|
4C198DEB29F88C6B004C165C /* BlurHashEncode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = "<group>"; };
|
||||||
4C198DEC29F88C6B004C165C /* Readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = "<group>"; };
|
4C198DEC29F88C6B004C165C /* Readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = "<group>"; };
|
||||||
4C198DED29F88C6B004C165C /* License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
|
4C198DED29F88C6B004C165C /* License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
|
||||||
@@ -974,6 +976,14 @@
|
|||||||
path = Zaps;
|
path = Zaps;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4C190F232A547D1700027FD5 /* NostrScript */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4C190F242A547D2000027FD5 /* LoadScript.swift */,
|
||||||
|
);
|
||||||
|
path = NostrScript;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4C198DEA29F88C6B004C165C /* BlurHash */ = {
|
4C198DEA29F88C6B004C165C /* BlurHash */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1048,6 +1058,7 @@
|
|||||||
4C75EFA227FA576C0006080F /* Views */ = {
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4C190F232A547D1700027FD5 /* NostrScript */,
|
||||||
4C7D09692A0AEA0400943473 /* CodeScanner */,
|
4C7D09692A0AEA0400943473 /* CodeScanner */,
|
||||||
4C7D095A2A098C5C00943473 /* Wallet */,
|
4C7D095A2A098C5C00943473 /* Wallet */,
|
||||||
4C8D1A6D29F31E4100ACDF75 /* Buttons */,
|
4C8D1A6D29F31E4100ACDF75 /* Buttons */,
|
||||||
@@ -1753,6 +1764,7 @@
|
|||||||
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
||||||
4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */,
|
4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */,
|
||||||
7C902AE32981D55B002AB16E /* ZoomableScrollView.swift in Sources */,
|
7C902AE32981D55B002AB16E /* ZoomableScrollView.swift in Sources */,
|
||||||
|
4C190F252A547D2000027FD5 /* LoadScript.swift in Sources */,
|
||||||
4CE8794C2995B59E00F758CC /* RelayMetadatas.swift in Sources */,
|
4CE8794C2995B59E00F758CC /* RelayMetadatas.swift in Sources */,
|
||||||
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
||||||
4CDA128A29E9D10C0006FA5A /* SignalView.swift in Sources */,
|
4CDA128A29E9D10C0006FA5A /* SignalView.swift in Sources */,
|
||||||
|
|||||||
@@ -224,6 +224,12 @@ struct ContentView: View {
|
|||||||
navigationCoordinator.push(route: Route.Wallet(wallet: damus_state!.wallet))
|
navigationCoordinator.push(route: Route.Wallet(wallet: damus_state!.wallet))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func open_script(_ script: [UInt8]) {
|
||||||
|
print("pushing script nav")
|
||||||
|
let model = ScriptModel(data: script, state: .not_loaded)
|
||||||
|
navigationCoordinator.push(route: Route.Script(script: model))
|
||||||
|
}
|
||||||
|
|
||||||
func open_profile(id: String) {
|
func open_profile(id: String) {
|
||||||
let profile_model = ProfileModel(pubkey: id, damus: damus_state!)
|
let profile_model = ProfileModel(pubkey: id, damus: damus_state!)
|
||||||
let followers = FollowersModel(damus_state: damus_state!, target: id)
|
let followers = FollowersModel(damus_state: damus_state!, target: id)
|
||||||
@@ -331,7 +337,9 @@ struct ContentView: View {
|
|||||||
case .filter(let filt): self.open_search(filt: filt)
|
case .filter(let filt): self.open_search(filt: filt)
|
||||||
case .profile(let id): self.open_profile(id: id)
|
case .profile(let id): self.open_profile(id: id)
|
||||||
case .event(let ev): self.open_event(ev: ev)
|
case .event(let ev): self.open_event(ev: ev)
|
||||||
case .wallet_connect(let nwc): self.open_wallet(nwc: nwc)}
|
case .wallet_connect(let nwc): self.open_wallet(nwc: nwc)
|
||||||
|
case .script(let data): self.open_script(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.compose)) { notif in
|
.onReceive(handle_notify(.compose)) { notif in
|
||||||
@@ -946,6 +954,7 @@ enum OpenResult {
|
|||||||
case filter(NostrFilter)
|
case filter(NostrFilter)
|
||||||
case event(NostrEvent)
|
case event(NostrEvent)
|
||||||
case wallet_connect(WalletConnectURL)
|
case wallet_connect(WalletConnectURL)
|
||||||
|
case script([UInt8])
|
||||||
}
|
}
|
||||||
|
|
||||||
func on_open_url(state: DamusState, url: URL, result: @escaping (OpenResult?) -> Void) {
|
func on_open_url(state: DamusState, url: URL, result: @escaping (OpenResult?) -> Void) {
|
||||||
@@ -973,5 +982,9 @@ func on_open_url(state: DamusState, url: URL, result: @escaping (OpenResult?) ->
|
|||||||
result(.filter(filt))
|
result(.filter(filt))
|
||||||
break
|
break
|
||||||
// TODO: handle filter searches?
|
// TODO: handle filter searches?
|
||||||
|
case .script(let script):
|
||||||
|
result(.script(script))
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import Foundation
|
|||||||
enum NostrLink: Equatable {
|
enum NostrLink: Equatable {
|
||||||
case ref(ReferencedId)
|
case ref(ReferencedId)
|
||||||
case filter(NostrFilter)
|
case filter(NostrFilter)
|
||||||
|
case script([UInt8])
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode_pubkey_uri(_ ref: ReferencedId) -> String {
|
func encode_pubkey_uri(_ ref: ReferencedId) -> String {
|
||||||
@@ -105,6 +106,8 @@ func decode_nostr_bech32_uri(_ s: String) -> NostrLink? {
|
|||||||
return .ref(ReferencedId(ref_id: pubkey, relay_id: nil, key: "p"))
|
return .ref(ReferencedId(ref_id: pubkey, relay_id: nil, key: "p"))
|
||||||
case .note(let id):
|
case .note(let id):
|
||||||
return .ref(ReferencedId(ref_id: id, relay_id: nil, key: "e"))
|
return .ref(ReferencedId(ref_id: id, relay_id: nil, key: "e"))
|
||||||
|
case .nscript(let data):
|
||||||
|
return .script(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ enum Bech32Object {
|
|||||||
case nsec(String)
|
case nsec(String)
|
||||||
case npub(String)
|
case npub(String)
|
||||||
case note(String)
|
case note(String)
|
||||||
|
case nscript([UInt8])
|
||||||
|
|
||||||
static func parse(_ str: String) -> Bech32Object? {
|
static func parse(_ str: String) -> Bech32Object? {
|
||||||
guard let decoded = try? bech32_decode(str) else {
|
guard let decoded = try? bech32_decode(str) else {
|
||||||
@@ -24,6 +25,8 @@ enum Bech32Object {
|
|||||||
return .nsec(hex_encode(decoded.data))
|
return .nsec(hex_encode(decoded.data))
|
||||||
} else if decoded.hrp == "note" {
|
} else if decoded.hrp == "note" {
|
||||||
return .note(hex_encode(decoded.data))
|
return .note(hex_encode(decoded.data))
|
||||||
|
} else if decoded.hrp == "nscript" {
|
||||||
|
return .nscript(decoded.data.bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ enum Route: Hashable {
|
|||||||
case Following(following: FollowingModel)
|
case Following(following: FollowingModel)
|
||||||
case MuteList(users: [String])
|
case MuteList(users: [String])
|
||||||
case RelayConfig
|
case RelayConfig
|
||||||
|
case Script(script: ScriptModel)
|
||||||
case Bookmarks
|
case Bookmarks
|
||||||
case Config
|
case Config
|
||||||
case EditMetadata
|
case EditMetadata
|
||||||
@@ -105,6 +106,8 @@ enum Route: Hashable {
|
|||||||
WalletScannerView(result: walletScanResult)
|
WalletScannerView(result: walletScanResult)
|
||||||
case .FollowersYouKnow(let friendedFollowers, let followers):
|
case .FollowersYouKnow(let friendedFollowers, let followers):
|
||||||
FollowersYouKnowView(damus_state: damusState, friended_followers: friendedFollowers, followers: followers)
|
FollowersYouKnowView(damus_state: damusState, friended_followers: friendedFollowers, followers: followers)
|
||||||
|
case .Script(let load_model):
|
||||||
|
LoadScript(pool: damusState.pool, model: load_model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +175,10 @@ enum Route: Hashable {
|
|||||||
return true
|
return true
|
||||||
case (.FollowersYouKnow(_, _), .FollowersYouKnow(_, _)):
|
case (.FollowersYouKnow(_, _), .FollowersYouKnow(_, _)):
|
||||||
return true
|
return true
|
||||||
|
case (.Script(_), .Script(_)):
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +264,9 @@ enum Route: Hashable {
|
|||||||
hasher.combine("followersYouKnow")
|
hasher.combine("followersYouKnow")
|
||||||
hasher.combine(friendedFollowers)
|
hasher.combine(friendedFollowers)
|
||||||
hasher.combine(followers.sub_id)
|
hasher.combine(followers.sub_id)
|
||||||
|
case .Script(let model):
|
||||||
|
hasher.combine("script")
|
||||||
|
hasher.combine(model.data.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
163
damus/Views/NostrScript/LoadScript.swift
Normal file
163
damus/Views/NostrScript/LoadScript.swift
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
//
|
||||||
|
// LoadScript.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2023-07-04.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ScriptLoaded {
|
||||||
|
let script: NostrScript
|
||||||
|
let state: LoadedState
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoadedState {
|
||||||
|
case loaded
|
||||||
|
case running
|
||||||
|
case ran(NostrScriptRunResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoadScriptState {
|
||||||
|
case not_loaded
|
||||||
|
case loading
|
||||||
|
case loaded(ScriptLoaded)
|
||||||
|
case failed(NostrScriptLoadErr)
|
||||||
|
|
||||||
|
static func loaded(script: NostrScript) -> LoadScriptState {
|
||||||
|
return .loaded(ScriptLoaded(script: script, state: .loaded))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScriptModel: ObservableObject {
|
||||||
|
var data: [UInt8]
|
||||||
|
@Published var state: LoadScriptState
|
||||||
|
|
||||||
|
init(data: [UInt8], state: LoadScriptState) {
|
||||||
|
self.data = data
|
||||||
|
self.state = state
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() async {
|
||||||
|
guard case .loaded(let script) = state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.state = .loaded(.init(script: script.script, state: .running))
|
||||||
|
|
||||||
|
let t = Task.detached {
|
||||||
|
return script.script.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = await t.value
|
||||||
|
self.state = .loaded(.init(script: script.script, state: .ran(res)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func load(pool: RelayPool) async {
|
||||||
|
guard case .not_loaded = state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.state = .loading
|
||||||
|
let script = NostrScript(pool: pool, data: self.data)
|
||||||
|
let t = Task.detached {
|
||||||
|
print("loading script")
|
||||||
|
return script.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
let load_err = await t.value
|
||||||
|
|
||||||
|
let t2 = Task { @MainActor in
|
||||||
|
if let load_err {
|
||||||
|
self.state = .failed(load_err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state = .loaded(script: script)
|
||||||
|
}
|
||||||
|
|
||||||
|
await t2.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoadScript: View {
|
||||||
|
let pool: RelayPool
|
||||||
|
|
||||||
|
@ObservedObject var model: ScriptModel
|
||||||
|
|
||||||
|
func ScriptView(_ script: ScriptLoaded) -> some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack {
|
||||||
|
let imports = script.script.imports()
|
||||||
|
|
||||||
|
(Text(verbatim: "\(imports.count)") +
|
||||||
|
Text(" Imports"))
|
||||||
|
.font(.title)
|
||||||
|
|
||||||
|
ForEach(imports.indices, id: \.self) { ind in
|
||||||
|
Text(imports[ind])
|
||||||
|
}
|
||||||
|
|
||||||
|
switch script.state {
|
||||||
|
case .loaded:
|
||||||
|
BigButton("Run") {
|
||||||
|
Task {
|
||||||
|
await model.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .running:
|
||||||
|
Text("Running...")
|
||||||
|
case .ran(let result):
|
||||||
|
switch result {
|
||||||
|
case .runtime_err(let errs):
|
||||||
|
Text("Runtime error")
|
||||||
|
.font(.title2)
|
||||||
|
ForEach(errs.indices, id: \.self) { ind in
|
||||||
|
Text(verbatim: errs[ind])
|
||||||
|
}
|
||||||
|
case .suspend:
|
||||||
|
Text("Ran to suspension.")
|
||||||
|
case .finished(let code):
|
||||||
|
Text("Executed successfuly, returned with code \(code)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
switch self.model.state {
|
||||||
|
case .not_loaded:
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
case .loading:
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
case .loaded(let loaded):
|
||||||
|
ScriptView(loaded)
|
||||||
|
case .failed(let load_err):
|
||||||
|
VStack(spacing: 20) {
|
||||||
|
Text("NostrScript Error")
|
||||||
|
.font(.title)
|
||||||
|
switch load_err {
|
||||||
|
case .parse:
|
||||||
|
Text("Failed to parse")
|
||||||
|
case .module_init:
|
||||||
|
Text("Failed to initialize")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
await model.load(pool: self.pool)
|
||||||
|
}
|
||||||
|
.navigationTitle("NostrScript")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#Preview {
|
||||||
|
LoadScript()
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -38,13 +38,13 @@ final class NostrScriptTests: XCTestCase {
|
|||||||
func test_bool_set() throws {
|
func test_bool_set() throws {
|
||||||
var data = try load_bool_set_test_wasm().bytes
|
var data = try load_bool_set_test_wasm().bytes
|
||||||
let pool = RelayPool()
|
let pool = RelayPool()
|
||||||
let script = NostrScript(pool: pool)
|
let script = NostrScript(pool: pool, data: data)
|
||||||
let pk = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
|
let pk = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
|
||||||
UserSettingsStore.pubkey = pk
|
UserSettingsStore.pubkey = pk
|
||||||
let key = pk_setting_key(pk, key: "nozaps")
|
let key = pk_setting_key(pk, key: "nozaps")
|
||||||
UserDefaults.standard.set(true, forKey: key)
|
UserDefaults.standard.set(true, forKey: key)
|
||||||
|
|
||||||
let load_err = script.load(wasm: &data)
|
let load_err = script.load()
|
||||||
XCTAssertNil(load_err)
|
XCTAssertNil(load_err)
|
||||||
|
|
||||||
let res = script.run()
|
let res = script.run()
|
||||||
@@ -62,9 +62,9 @@ final class NostrScriptTests: XCTestCase {
|
|||||||
func test_nostrscript() throws {
|
func test_nostrscript() throws {
|
||||||
var data = try loadTestWasm().bytes
|
var data = try loadTestWasm().bytes
|
||||||
let pool = RelayPool()
|
let pool = RelayPool()
|
||||||
let script = NostrScript(pool: pool)
|
let script = NostrScript(pool: pool, data: data)
|
||||||
|
|
||||||
let load_err = script.load(wasm: &data)
|
let load_err = script.load()
|
||||||
XCTAssertNil(load_err)
|
XCTAssertNil(load_err)
|
||||||
|
|
||||||
let res = script.run()
|
let res = script.run()
|
||||||
|
|||||||
@@ -41,21 +41,29 @@ enum NostrScriptLoadResult {
|
|||||||
case loaded(wasm_interp)
|
case loaded(wasm_interp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum NostrScriptError: Error {
|
||||||
|
case not_loaded
|
||||||
|
}
|
||||||
|
|
||||||
class NostrScript {
|
class NostrScript {
|
||||||
private var interp: wasm_interp
|
private var interp: wasm_interp
|
||||||
private var parser: wasm_parser
|
private var parser: wasm_parser
|
||||||
var waiting_on: NScriptWaiting?
|
var waiting_on: NScriptWaiting?
|
||||||
|
var loaded: Bool
|
||||||
|
var data: [UInt8]
|
||||||
|
|
||||||
private(set) var runstate: NostrScriptRunResult?
|
private(set) var runstate: NostrScriptRunResult?
|
||||||
private(set) var pool: RelayPool
|
private(set) var pool: RelayPool
|
||||||
private(set) var event: NostrResponse?
|
private(set) var event: NostrResponse?
|
||||||
|
|
||||||
init(pool: RelayPool) {
|
init(pool: RelayPool, data: [UInt8]) {
|
||||||
self.interp = wasm_interp()
|
self.interp = wasm_interp()
|
||||||
self.parser = wasm_parser()
|
self.parser = wasm_parser()
|
||||||
self.pool = pool
|
self.pool = pool
|
||||||
self.event = nil
|
self.event = nil
|
||||||
self.runstate = nil
|
self.runstate = nil
|
||||||
|
self.loaded = false
|
||||||
|
self.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@@ -80,15 +88,37 @@ class NostrScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func test(_ str: String) {
|
func imports() -> [String] {
|
||||||
print("hello from \(str)")
|
guard self.loaded,
|
||||||
|
was_section_parsed(interp.module, section_import) > 0,
|
||||||
|
let module = maybe_pointee(interp.module)
|
||||||
|
else {
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
func load(wasm: inout [UInt8]) -> NostrScriptLoadErr? {
|
var imports = [String]()
|
||||||
switch nscript_load(&parser, &interp, &wasm, UInt(wasm.count)) {
|
|
||||||
|
var i = 0
|
||||||
|
while i < module.import_section.num_imports {
|
||||||
|
let imp = module.import_section.imports[i]
|
||||||
|
|
||||||
|
imports.append(String(cString: imp.name))
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return imports
|
||||||
|
}
|
||||||
|
|
||||||
|
func load() -> NostrScriptLoadErr? {
|
||||||
|
guard !loaded else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch nscript_load(&parser, &interp, &self.data, UInt(data.count)) {
|
||||||
case NSCRIPT_LOADED:
|
case NSCRIPT_LOADED:
|
||||||
print("load num_exports \(interp.module.pointee.export_section.num_exports)")
|
print("load num_exports \(interp.module.pointee.export_section.num_exports)")
|
||||||
interp.context = Unmanaged.passUnretained(self).toOpaque()
|
interp.context = Unmanaged.passUnretained(self).toOpaque()
|
||||||
|
self.loaded = true
|
||||||
return nil
|
return nil
|
||||||
case NSCRIPT_INIT_ERR:
|
case NSCRIPT_INIT_ERR:
|
||||||
return .module_init
|
return .module_init
|
||||||
@@ -292,7 +322,9 @@ public func nscript_set_bool(interp: UnsafeMutablePointer<wasm_interp>?, setting
|
|||||||
}
|
}
|
||||||
|
|
||||||
let key = pk_setting_key(UserSettingsStore.pubkey ?? "", key: setting)
|
let key = pk_setting_key(UserSettingsStore.pubkey ?? "", key: setting)
|
||||||
UserDefaults.standard.set(val > 0 ? true : false, forKey: key)
|
let b = val > 0 ? true : false
|
||||||
|
print("nscript setting bool setting \(setting) to \(b)")
|
||||||
|
UserDefaults.standard.set(b, forKey: key)
|
||||||
|
|
||||||
stack_push_i32(interp, 1);
|
stack_push_i32(interp, 1);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -316,7 +348,7 @@ public func nscript_pool_send_to(interp: UnsafeMutablePointer<wasm_interp>?, pre
|
|||||||
}
|
}
|
||||||
|
|
||||||
func nscript_pool_send(script: NostrScript, req req_str: String) -> Int32 {
|
func nscript_pool_send(script: NostrScript, req req_str: String) -> Int32 {
|
||||||
script.test("pool_send: '\(req_str)'")
|
//script.test("pool_send: '\(req_str)'")
|
||||||
|
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
script.pool.send_raw(.custom(req_str), skip_ephemeral: false)
|
script.pool.send_raw(.custom(req_str), skip_ephemeral: false)
|
||||||
|
|||||||
Reference in New Issue
Block a user