Skip to content

Commit 762c1f0

Browse files
authored
Merge pull request #5546 from StachuDotNet/jsoncanvas-experiment
misc experiment with json canvas
2 parents e21ac9e + 2285fce commit 762c1f0

File tree

4 files changed

+588
-11
lines changed

4 files changed

+588
-11
lines changed

.devcontainer/devcontainer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
// as we see in script/builder
4040
/////////////////////////////////////////////////
4141

42-
// Ports are loaded in the build process
4342
// Ports: 10011-10030 are test servers, 11001-11002 are BwdServer
44-
"forwardPorts": [10011, 10012, 10030, 11001, 11002],
43+
// 9090-9099 are for ad-hoc http-server demos
44+
"forwardPorts": [10011, 10012, 10030, 11001, 11002, 9090, 9091, 9092, 9093, 9094, 9095, 9096, 9097, 9098, 9099],
4545

4646
"containerEnv": {
4747
"IN_DEV_CONTAINER": "true"

packages/darklang/cli/commands/http-server.dark

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ module Darklang.Cli.Commands.HttpServer
22

33
// Run an HTTP server
44

5+
// TODO: dynamically resolve router by name instead of hardcoding.
6+
//
7+
// Approaches tried:
8+
// 1. pmFindValue + pmEvaluateValue: finds the value and evaluates it, but
9+
// lambda Dvals don't carry their instruction cache (LambdaImpl), so calling
10+
// them from a different execution context (e.g. ASP.NET request handler)
11+
// fails with "lambda not found" (exprId missing from VM's lambdaInstrCache).
12+
// 2. cliEvaluateExpression to build "Stdlib.HttpServer.serve {port}L {name}":
13+
// same underlying issue — the function resolves as AppNamedFn inside the
14+
// eval VM, but httpServerServe's ASP.NET handler runs in a separate context
15+
// where the instruction caches from the eval VM aren't available.
16+
//
17+
// The fix likely requires either:
18+
// - Making the httpServerServe builtin propagate the VM's instruction cache
19+
// to the ASP.NET request handler thread
20+
// - Or adding a builtin that resolves+calls a package fn by name in a single
21+
// execution context (avoiding the cross-context lambda problem)
22+
// See also: PR #5582 (reflection support), PR #5546 (original json-canvas)
23+
524
let execute (state: Cli.AppState) (args: List<String>) : Cli.AppState =
625
match args with
726
| [] ->
8-
[ "Usage: http-server <port> [router-path]"
27+
[ "Usage: http-server <port> <router-path>"
928
""
1029
"Examples:"
1130
" http-server 8080"
@@ -28,7 +47,6 @@ let execute (state: Cli.AppState) (args: List<String>) : Cli.AppState =
2847
"" ]
2948
|> Stdlib.printLines
3049

31-
// Use the test router by default
3250
Stdlib.HttpServer.serve port DemoData.HttpServerTest.router
3351

3452
state
@@ -41,32 +59,34 @@ let execute (state: Cli.AppState) (args: List<String>) : Cli.AppState =
4159
| Ok port ->
4260
let portStr_ = Stdlib.Int64.toString port
4361

44-
[ $"Starting HTTP server on port {portStr_}..."
45-
$"Using router: {routerPath}"
62+
[ $"Using router: {routerPath}"
4663
""
4764
Colors.success $"Listening on http://localhost:{portStr_}"
4865
"Press Ctrl+C to stop"
4966
"" ]
5067
|> Stdlib.printLines
5168

52-
// Known routers - Darklang doesn't support dynamic function lookup at runtime
5369
match routerPath with
5470
| "Darklang.Canvas.DarkPackages.router" ->
5571
Stdlib.HttpServer.serve port Darklang.Canvas.DarkPackages.router
5672
state
5773
| "Darklang.DemoData.HttpServerTest.router" ->
5874
Stdlib.HttpServer.serve port DemoData.HttpServerTest.router
5975
state
76+
| "Stachu.JsonCanvas.Server.router" ->
77+
Stdlib.HttpServer.serve port Stachu.JsonCanvas.Server.router
78+
state
6079
| _ ->
6180
[ Colors.error $"Unknown router: {routerPath}"
6281
"Known routers:"
6382
" - Darklang.Canvas.DarkPackages.router"
64-
" - Darklang.DemoData.HttpServerTest.router" ]
83+
" - Darklang.DemoData.HttpServerTest.router"
84+
" - Stachu.JsonCanvas.Server.router" ]
6585
|> Stdlib.printLines
6686
state
6787

6888
| _ ->
69-
Stdlib.printLine "Usage: http-server <port> [router-path]"
89+
Stdlib.printLine "Usage: http-server <port> <router-path>"
7090
state
7191

7292

@@ -77,11 +97,11 @@ let help (state: Cli.AppState) : Cli.AppState =
7797
""
7898
"Arguments:"
7999
" port Port to listen on (e.g., 8080)"
80-
" router-path Optional path to router function (e.g., Darklang.Canvas.DarkPackages.router)"
100+
" router-path Dotted path to a router function"
81101
""
82102
"Examples:"
83103
" http-server 8080"
84-
" http-server 8080 Darklang.Canvas.DarkPackages.router" ]
104+
" http-server 8080 Stachu.JsonCanvas.Server.router" ]
85105
|> Stdlib.printLines
86106

87107
state

packages/darklang/cli/docs/for-ai-internal.dark

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ Use `expect` via run-in-docker for automated interactive testing:
8181
Telemetry data lands in rundir/logs/telemetry.jsonl.
8282
Full guide: `docs interactive-testing`
8383

84+
## HTTP Server Demo
85+
http-server <port> <router> # serve a Darklang router function
86+
Use ports 9090-9099 for demos (forwarded from devcontainer to host).
87+
Kill anything already on the port if needed.
88+
Known limitation: httpServerServe runs handlers in a fresh execution
89+
context without lambda instruction caches, so handlers that use
90+
lambdas (List.map, routeRequest, etc.) will fail at runtime.
91+
Workaround: avoid lambdas in handler call chains, or pre-compute results.
92+
8493
## Debug
8594
Builtin.debug "label" value # prints DEBUG: label: <repr> to stdout
8695
eval <expr> # test small pieces (uses tree-sitter parser, not F# parser)

0 commit comments

Comments
 (0)