about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-01 13:44:36 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-01 16:42:58 +0200
commitc55e4f5ef3c57ad7cfd7bc35546fdd5dc3a81bf1 (patch)
tree4e276c5a6a3ea9771d62ab0988bcf981a301ae97
parenta2467edbd458eed9bec16ec8cddcb89c86a0b156 (diff)
downloadchawan-c55e4f5ef3c57ad7cfd7bc35546fdd5dc3a81bf1.tar.gz
buffer: add javascript: URL support
Caveats:
* only works in buffers, no navigation yet
* converts the output result into a data URL, but data URLs are
  not supported yet...

If JS is disabled, we simply do nothing.
-rw-r--r--src/buffer/buffer.nim42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim
index 94389e58..c87a6181 100644
--- a/src/buffer/buffer.nim
+++ b/src/buffer/buffer.nim
@@ -9,6 +9,7 @@ import streams
 import tables
 import unicode
 
+import bindings/quickjs
 import buffer/cell
 import config/config
 import css/cascade
@@ -32,6 +33,7 @@ import ips/serialize
 import ips/serversocket
 import ips/socketstream
 import js/error
+import js/fromjs
 import js/javascript
 import js/regex
 import js/timeout
@@ -1083,13 +1085,47 @@ proc click(buffer: Buffer, select: HTMLSelectElement): ClickResult =
     select: some(select)
   )
 
+func baseURL(buffer: Buffer): URL =
+  return buffer.document.baseURL
+
+proc evalJSURL(buffer: Buffer, url: URL): Opt[string] =
+  let encodedScriptSource = ($url)["javascript:".len..^1]
+  let scriptSource = percentDecode(encodedScriptSource)
+  let ctx = buffer.window.jsctx
+  let ret = ctx.eval(scriptSource, $buffer.baseURL, JS_EVAL_TYPE_GLOBAL)
+  if JS_IsException(ret):
+    ctx.writeException(buffer.estream)
+    return err() # error
+  if JS_IsUndefined(ret):
+    return err() # no need to navigate
+  let s = ?fromJS[string](ctx, ret)
+  JS_FreeValue(ctx, ret)
+  # Navigate to result.
+  return ok(s)
+
 proc click(buffer: Buffer, anchor: HTMLAnchorElement): ClickResult =
-  let repaint = buffer.restoreFocus()
-  let url = parseURL(anchor.href, some(anchor.document.baseURL))
+  var repaint = buffer.restoreFocus()
+  let url = parseURL(anchor.href, some(buffer.baseURL))
   if url.isSome:
+    let url = url.get
+    if url.scheme == "javascript":
+      if buffer.config.scripting:
+        let s = buffer.evalJSURL(url)
+        buffer.do_reshape()
+        repaint = true
+        if s.isSome:
+          let url = newURL("data:text/html," & s.get).get
+          let req = newRequest(url, HTTP_GET)
+          return ClickResult(
+            repaint: repaint,
+            open: some(req)
+          )
+      return ClickResult(
+        repaint: repaint
+      )
     return ClickResult(
       repaint: repaint,
-      open: some(newRequest(url.get, HTTP_GET))
+      open: some(newRequest(url, HTTP_GET))
     )
   return ClickResult(
     repaint: repaint