| 1 | // Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | |
| 5 | // This file contains JS functions present in both node and the browser. |
| 6 | // They have been ported from their TypeScript definitions. |
| 7 | |
| 8 | module builtin |
| 9 | |
| 10 | pub interface JS.Object {} |
| 11 | |
| 12 | @[single_impl] |
| 13 | pub interface JS.BigInt { |
| 14 | JS.Any |
| 15 | } |
| 16 | |
| 17 | @[single_impl] |
| 18 | pub interface JS.Number { |
| 19 | JS.Any |
| 20 | } |
| 21 | |
| 22 | pub interface JS.RegExp { |
| 23 | JS.Any |
| 24 | } |
| 25 | |
| 26 | pub type SplitSeparator = JS.RegExp | JS.String |
| 27 | |
| 28 | @[single_impl] |
| 29 | pub interface JS.String { |
| 30 | JS.Any |
| 31 | length JS.Number |
| 32 | charAt(index JS.Number) JS.String |
| 33 | charCodeAt(index JS.Number) JS.Number |
| 34 | toUpperCase() JS.String |
| 35 | toLowerCase() JS.String |
| 36 | concat(a JS.String) JS.String |
| 37 | includes(substr JS.String) JS.Boolean |
| 38 | endsWith(substr JS.String) JS.Boolean |
| 39 | startsWith(substr JS.String) JS.Boolean |
| 40 | slice(a JS.Number, b JS.Number) JS.String |
| 41 | split(delim SplitSeparator) JS.Array |
| 42 | indexOf(needle JS.String) JS.Number |
| 43 | lastIndexOf(needle JS.String) JS.Number |
| 44 | } |
| 45 | |
| 46 | @[single_impl] |
| 47 | pub interface JS.Boolean { |
| 48 | JS.Any |
| 49 | length JS.Number |
| 50 | } |
| 51 | |
| 52 | pub interface JS.Map { |
| 53 | JS.Any |
| 54 | size JS.Number |
| 55 | clear() |
| 56 | delete(key JS.Any) JS.Boolean |
| 57 | get(key JS.Any) JS.Any |
| 58 | has(key JS.Any) JS.Any |
| 59 | set(key JS.Any, val JS.Any) |
| 60 | } |
| 61 | |
| 62 | #function Any(val) { return val; } |
| 63 | |
| 64 | pub interface JS.Any {} |
| 65 | |
| 66 | pub fn js_is_null(x JS.Any) bool { |
| 67 | res := false |
| 68 | #res.val = x === null |
| 69 | |
| 70 | return res |
| 71 | } |
| 72 | |
| 73 | pub fn js_is_undefined(x JS.Any) bool { |
| 74 | res := false |
| 75 | #res.val = x === undefined |
| 76 | |
| 77 | return res |
| 78 | } |
| 79 | |
| 80 | pub fn js_null() JS.Any { |
| 81 | mut obj := JS.Any{} |
| 82 | #obj = null; |
| 83 | |
| 84 | return obj |
| 85 | } |
| 86 | |
| 87 | pub fn js_undefined() JS.Any { |
| 88 | mut obj := JS.Any{} |
| 89 | #obj = undefined; |
| 90 | |
| 91 | return obj |
| 92 | } |
| 93 | |
| 94 | pub interface JS.Array { |
| 95 | JS.Any // map(fn (JS.Any) JS.Any) JS.Array |
| 96 | map(JS.Any) JS.Array |
| 97 | push(JS.Any) JS.Any |
| 98 | pop() JS.Any |
| 99 | at(JS.Number) JS.Any |
| 100 | mut: |
| 101 | length JS.Number |
| 102 | } |
| 103 | |
| 104 | pub fn JS.Array.prototype.constructor(...any) JS.Array |
| 105 | |
| 106 | // browser: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Error |
| 107 | // node: https://nodejs.org/api/errors.html#errors_class_error |
| 108 | pub struct JS.Error { |
| 109 | pub: |
| 110 | name string |
| 111 | message string |
| 112 | stack string |
| 113 | } |
| 114 | |
| 115 | // Type prototype functions |
| 116 | fn (v JS.String) toString() JS.String |
| 117 | fn (v JS.Number) toString() JS.String |
| 118 | fn (v JS.Boolean) toString() JS.String |
| 119 | fn (v JS.Array) toString() JS.String |
| 120 | fn (v JS.Map) toString() JS.String |
| 121 | |
| 122 | // Hack for "`[]JS.String` is not a struct" when returning arr.length or arr.len |
| 123 | // TODO: Fix []JS.String not a struct error |
| 124 | fn native_str_arr_len(arr []JS.String) int { |
| 125 | mut len := 0 |
| 126 | #len = arr.length |
| 127 | |
| 128 | return len |
| 129 | } |
| 130 | |
| 131 | // Top level functions |
| 132 | fn JS.eval(JS.String) JS.Any |
| 133 | fn JS.parseInt(JS.String, f64) JS.Number |
| 134 | fn JS.parseFloat(JS.String) JS.Number |
| 135 | fn JS.isNaN(f64) bool |
| 136 | fn JS.isFinite(f64) bool |
| 137 | fn JS.decodeURI(JS.String) JS.String |
| 138 | fn JS.decodeURIComponent(JS.String) JS.String |
| 139 | fn JS.encodeURI(JS.String) JS.String |
| 140 | |
| 141 | type EncodeURIComponentArg = JS.String | bool | f64 |
| 142 | |
| 143 | fn JS.encodeURIComponent(EncodeURIComponentArg) JS.String |
| 144 | fn JS.escape(JS.String) JS.String |
| 145 | fn JS.unescape(JS.String) JS.String |
| 146 | |
| 147 | // console |
| 148 | fn JS.console.assert(bool, ...any) |
| 149 | fn JS.console.clear() |
| 150 | fn JS.console.count(JS.String) |
| 151 | fn JS.console.countReset(JS.String) |
| 152 | fn JS.console.debug(...any) |
| 153 | fn JS.console.dir(any, any) |
| 154 | fn JS.console.dirxml(...any) |
| 155 | fn JS.console.error(...any) |
| 156 | fn JS.console.exception(string, ...any) |
| 157 | fn JS.console.group(...any) |
| 158 | fn JS.console.groupCollapsed(...any) |
| 159 | fn JS.console.groupEnd() |
| 160 | fn JS.console.info(...any) |
| 161 | fn JS.console.log(...any) |
| 162 | fn JS.console.table(any, []string) |
| 163 | fn JS.console.time(JS.String) |
| 164 | fn JS.console.timeEnd(JS.String) |
| 165 | fn JS.console.timeLog(string, ...any) |
| 166 | fn JS.console.timeStamp(string) |
| 167 | fn JS.console.trace(...any) |
| 168 | fn JS.console.warn(...any) |
| 169 | |
| 170 | // Math |
| 171 | fn JS.Math.abs(f64) f64 |
| 172 | fn JS.Math.acos(f64) f64 |
| 173 | fn JS.Math.asin(f64) f64 |
| 174 | fn JS.Math.atan(f64) f64 |
| 175 | fn JS.Math.atan2(f64, f64) f64 |
| 176 | fn JS.Math.ceil(f64) f64 |
| 177 | fn JS.Math.cos(f64) f64 |
| 178 | fn JS.Math.exp(f64) f64 |
| 179 | fn JS.Math.floor(f64) f64 |
| 180 | fn JS.Math.log(f64) f64 |
| 181 | fn JS.Math.max(...f64) f64 |
| 182 | fn JS.Math.min(...f64) f64 |
| 183 | fn JS.Math.pow(f64, f64) f64 |
| 184 | fn JS.Math.random() f64 |
| 185 | fn JS.Math.round(f64) f64 |
| 186 | fn JS.Math.sin(f64) f64 |
| 187 | fn JS.Math.sqrt(f64) f64 |
| 188 | fn JS.Math.tan(f64) f64 |
| 189 | |
| 190 | // JSON |
| 191 | fn JS.JSON.stringify(any) JS.String |
| 192 | fn JS.JSON.parse(string) any |
| 193 | |