about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/html/dom.nim14
-rw-r--r--src/io/request.nim10
-rw-r--r--src/js/intl.nim2
-rw-r--r--src/js/javascript.nim6
-rw-r--r--src/types/blob.nim44
-rw-r--r--src/xhr/formdata.nim14
6 files changed, 62 insertions, 28 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 190dd479..b022d858 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -370,7 +370,8 @@ proc resetState(state: var DrawingState) =
   state.strokeStyle = rgba(0, 0, 0, 255)
   state.path = newPath()
 
-proc create2DContext*(target: HTMLCanvasElement, options: Option[JSObject]):
+proc create2DContext*(jctx: JSContext, target: HTMLCanvasElement,
+    options: Option[JSValue]):
     CanvasRenderingContext2D =
   let ctx = CanvasRenderingContext2D(
     bitmap: target.bitmap,
@@ -2720,23 +2721,22 @@ func getElementReflectFunctions(): seq[TabGetSet] =
     result.add(TabGetSet(name: ReflectTable[i].funcname, get: jsReflectGet, set: jsReflectSet, magic: i))
     inc i
 
-proc getContext*(this: HTMLCanvasElement, contextId: string,
-    options = none(JSObject)): RenderingContext {.jsfunc.} =
+proc getContext*(jctx: JSContext, this: HTMLCanvasElement, contextId: string,
+    options = none(JSValue)): RenderingContext {.jsfunc.} =
   if contextId == "2d":
     if this.ctx2d != nil:
       return this.ctx2d
-    return create2DContext(this, options)
+    return create2DContext(jctx, this, options)
   return nil
 
 #TODO quality should be `any'
-proc toBlob(this: HTMLCanvasElement, callback: JSObject,
+proc toBlob(ctx: JSContext, this: HTMLCanvasElement, callback: JSValue,
     s = "image/png", quality: float64 = 1): JSValue {.jsfunc.} =
-  let ctx = callback.ctx
   var outlen: int
   let buf = this.bitmap.toPNG(outlen)
   let blob = newBlob(buf, outlen, "image/png", dealloc)
   var jsBlob = toJS(ctx, blob)
-  let res = JS_Call(ctx, callback.val, JS_UNDEFINED, 1, addr jsBlob)
+  let res = JS_Call(ctx, callback, JS_UNDEFINED, 1, addr jsBlob)
   # Hack. TODO: implement JSValue to callback
   if res == JS_EXCEPTION:
     return JS_EXCEPTION
diff --git a/src/io/request.nim b/src/io/request.nim
index 08947bd5..ed38ad47 100644
--- a/src/io/request.nim
+++ b/src/io/request.nim
@@ -186,10 +186,13 @@ proc fill(headers: Headers, ctx: JSContext, val: JSValue) =
         else:
           headers.table[k] = @[v]
 
-func newHeaders*(obj = none(JSObject)): Headers {.jsctor.} =
+func newHeaders*(): Headers =
+  new(result)
+
+func newHeaders*(ctx: JSContext, obj = none(JSValue)): Headers {.jsctor.} =
   new(result)
   if obj.isSome:
-    result.fill(obj.get.ctx, obj.get.val)
+    result.fill(ctx, obj.get)
 
 func newHeaders*(table: Table[string, string]): Headers =
   new(result)
@@ -239,8 +242,7 @@ func createPotentialCORSRequest*(url: URL, destination: RequestDestination, cors
   return newRequest(url, destination = destination, mode = mode, credentialsMode = credentialsMode)
 
 #TODO resource as Request
-#TODO also, I'm not sure what to do with init. For now I've re-introduced
-# JSObject to make this work, but I really wish we had a better solution.
+#TODO init as an actual dictionary
 func newRequest*(ctx: JSContext, resource: string,
     init = none(JSValue)): Request {.jserr, jsctor.} =
   let x = parseURL(resource)
diff --git a/src/js/intl.nim b/src/js/intl.nim
index 28cc42d5..f37789ad 100644
--- a/src/js/intl.nim
+++ b/src/js/intl.nim
@@ -8,7 +8,7 @@ type
 
 #TODO ...yeah
 proc newNumberFormat(name: string = "en-US",
-    options = none(JSObject)): NumberFormat {.jsctor.} =
+    options = none(JSValue)): NumberFormat {.jsctor.} =
   return NumberFormat()
 
 #TODO: this should accept string/BigInt too
diff --git a/src/js/javascript.nim b/src/js/javascript.nim
index 4eefd1b6..17bc555a 100644
--- a/src/js/javascript.nim
+++ b/src/js/javascript.nim
@@ -85,10 +85,6 @@ type
 
   JSFunctionList* = openArray[JSCFunctionListEntry]
 
-  JSObject* = object
-    ctx*: JSContext
-    val*: JSValue
-
 func getOpaque*(ctx: JSContext): JSContextOpaque =
   return cast[JSContextOpaque](JS_GetContextOpaque(ctx))
 
@@ -703,8 +699,6 @@ proc fromJS*[T](ctx: JSContext, val: JSValue): Option[T] =
       return none(T)
   elif T is JSValue:
     return some(val)
-  elif T is JSObject:
-    return some(JSObject(ctx: ctx, val: val))
   elif T is object:
     doAssert false, "Dictionary case has not been implemented yet!"
     #TODO TODO TODO implement dictionary case
diff --git a/src/types/blob.nim b/src/types/blob.nim
index 677fb037..4a5627c3 100644
--- a/src/types/blob.nim
+++ b/src/types/blob.nim
@@ -1,3 +1,5 @@
+import options
+
 import js/javascript
 import types/mime
 import utils/twtstr
@@ -37,17 +39,47 @@ proc newWebFile*(path: string, webkitRelativePath = ""): WebFile =
     isfile: true,
     path: path,
     file: file,
+    ctype: guessContentType(path),
     webkitRelativePath: webkitRelativePath
   )
 
+proc newWebFile(ctx: JSContext, fileBits: seq[string], fileName: string,
+    options = none(JSValue)): WebFile {.jsctor.} =
+  let file = WebFile(
+    isfile: false,
+    path: fileName,
+    deallocFun: dealloc
+  )
+  var len = 0
+  for blobPart in fileBits:
+    len += blobPart.len
+  file.buffer = alloc(len)
+  var buf = cast[ptr UncheckedArray[uint8]](file.buffer)
+  var i = 0
+  for blobPart in fileBits:
+    if blobPart.len > 0:
+      copyMem(addr buf[i], unsafeAddr blobPart[0], blobPart.len)
+      i += blobPart.len
+  file.size = uint64(len)
+  if options.isSome:
+    block ctype:
+      let t = fromJS[string](ctx, JS_GetPropertyStr(ctx, options.get, "type"))
+      if t.isNone:
+        break ctype
+      for c in t.get:
+        if c notin char(0x20)..char(0x7E):
+          break ctype
+        file.ctype &= c.tolower()
+    #TODO lastmodified
+  return file
+
 #TODO File, Blob constructors
 
 func size*(this: WebFile): uint64 {.jsfget.} =
   #TODO use stat instead
-  return uint64(this.file.getFileSize())
-
-func ctype*(this: WebFile): string {.jsfget: "type".} =
-  return guessContentType(this.path)
+  if this.isfile:
+    return uint64(this.file.getFileSize())
+  return this.size
 
 func name*(this: WebFile): string {.jsfget.} =
   if this.path.len > 0 and this.path[^1] != '/':
@@ -57,5 +89,5 @@ func name*(this: WebFile): string {.jsfget.} =
 #TODO lastModified
 
 proc addBlobModule*(ctx: JSContext) =
-  ctx.registerType(Blob)
-  ctx.registerType(WebFile, name = "File")
+  let blobCID = ctx.registerType(Blob)
+  ctx.registerType(WebFile, parent = blobCID, name = "File")
diff --git a/src/xhr/formdata.nim b/src/xhr/formdata.nim
index 9b45e7ba..cbb9f63e 100644
--- a/src/xhr/formdata.nim
+++ b/src/xhr/formdata.nim
@@ -40,13 +40,19 @@ proc append*(this: FormData, name: string, value: Blob,
   ))
 
 #TODO hack
-proc append(this: FormData, name: string, value: JSObject,
+proc append(ctx: JSContext, this: FormData, name: string, value: JSValue,
     filename = none(string)) {.jsfunc.} =
-  let blob = fromJS[Blob](value.ctx, value.val)
+  let blob = fromJS[Blob](ctx, value)
   if blob.isSome:
-    this.append(name, blob.get, filename.get("blob"))
+    let filename = if filename.isSome:
+      filename.get
+    elif blob.get of WebFile:
+      WebFile(blob.get).name
+    else:
+      "blob"
+    this.append(name, blob.get, filename)
   else:
-    let s = fromJS[string](value.ctx, value.val)
+    let s = fromJS[string](ctx, value)
     # toString should never fail (?)
     this.append(name, s.get, filename.get(""))