js: implement more functions for JS backend (#12167)

pull/12170/head
playX 2021-10-13 09:40:14 +03:00 committed by GitHub
parent ade5774313
commit d373eba79b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 134 additions and 3 deletions

View File

@ -2,8 +2,11 @@ module builtin
// used to generate JS throw statements.
[noreturn]
pub fn js_throw(s any) {
#throw s
for {}
}
#let globalPrint;
@ -46,6 +49,7 @@ pub fn eprint(s string) {
// Exits the process in node, and halts execution in the browser
// because `process.exit` is undefined. Workaround for not having
// a 'real' way to exit in the browser.
[noreturn]
pub fn exit(c int) {
JS.process.exit(c)
js_throw('exit($c)')

View File

@ -68,3 +68,29 @@ pub fn (c byte) is_letter() bool {
pub fn (c byte) is_alnum() bool {
return c.is_letter() || c.is_digit()
}
// Define this on byte as well, so that we can do `s[0].is_capital()`
pub fn (c byte) is_capital() bool {
return c >= `A` && c <= `Z`
}
// str_escaped returns the contents of `byte` as an escaped `string`.
// Example: assert byte(0).str_escaped() == r'`\0`'
pub fn (b byte) str_escaped() string {
mut str := ''
match b {
0 { str = r'`\0`' }
7 { str = r'`\a`' }
8 { str = r'`\b`' }
9 { str = r'`\t`' }
10 { str = r'`\n`' }
11 { str = r'`\v`' }
12 { str = r'`\f`' }
13 { str = r'`\r`' }
27 { str = r'`\e`' }
32...126 { str = b.ascii_str() }
else { str = '0x' + b.hex() }
}
return str
}

View File

@ -900,3 +900,13 @@ pub fn (s []string) join(sep string) string {
// There's no better way to find length of JS String in bytes.
#Object.defineProperty(string.prototype,"len", { get: function() {return new int(new TextEncoder().encode(this.str).length);}, set: function(l) {/* ignore */ } });
// index returns the position of the first character of the input string.
// It will return `none` if the input string can't be found.
pub fn (s string) index(search string) ?int {
res := 0
#res.val = s.str.indexOf(search)
if res == -1 {
return none
}
return res
}

View File

@ -37,19 +37,36 @@ pub fn flush() {
}
}
pub fn getpid() int {
res := 0
#res.val = $process.pid
return res
}
// chmod change file access attributes of `path` to `mode`.
// Octals like `0o600` can be used.
pub fn chmod(path string, mode int) {
pub fn chmod(path string, mode int) ? {
$if js_node {
#try {
#$fs.chmodSync(''+path,mode.valueOf())
#} catch (error) {
#return error_with_code(new string("chmod failed: " + error.message),new int(error.code))
#}
} $else {
return error('os.chmod() is available only for NodeJS')
}
}
// chown changes the owner and group attributes of `path` to `owner` and `group`.
// Octals like `0o600` can be used.
pub fn chown(path string, owner int, group int) {
pub fn chown(path string, owner int, group int) ? {
$if js_node {
#try {
#$fs.chownSync(''+path,owner.valueOf(),group.valueOf())
#} catch (error) { return error_with_code(new string("chown failed: " + error.message),new int(error.code)) }
} $else {
return error('os.chown() is available only for NodeJS')
}
}
@ -89,7 +106,7 @@ pub fn execute(cmd string) Result {
#let commands = cmd.str.split(' ');
#let output = $child_process.spawnSync(commands[0],commands.slice(1,commands.length));
#exit_code = new int(output.status)
#stdout = newstring(output.stdout + '')
#stdout = new string(output.stdout + '')
return Result{
exit_code: exit_code
@ -97,6 +114,14 @@ pub fn execute(cmd string) Result {
}
}
pub fn system(cmd string) int {
exit_code := 0
#let commands = cmd.str.split(' ');
#exit_code.val = $child_process.execSync(commands[0],commands.slice(1,commands.length));
return exit_code
}
pub fn is_atty(fd int) int {
res := 0
#res.val = +tty.isatty(fd.val)

View File

@ -1,5 +1,7 @@
module rand
import time
// init initializes the default RNG.
fn init() {
default_rng = new_default()
@ -15,3 +17,51 @@ pub fn string(len int) string {
return result
}
const (
ulid_encoding = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
)
// ulid generates an Unique Lexicographically sortable IDentifier.
// See https://github.com/ulid/spec .
// NB: ULIDs can leak timing information, if you make them public, because
// you can infer the rate at which some resource is being created, like
// users or business transactions.
// (https://news.ycombinator.com/item?id=14526173)
pub fn ulid() string {
return ulid_at_millisecond(u64(time.utc().unix_time_milli()))
}
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`.
pub fn ulid_at_millisecond(unix_time_milli u64) string {
mut buf := []byte{cap: 27}
mut t := unix_time_milli
mut i := 9
for i >= 0 {
buf[i] = rand.ulid_encoding[int(t & 0x1f)]
t = t >> 5
i--
}
mut x := default_rng.u64()
i = 10
for i < 19 {
buf[i] = rand.ulid_encoding[int(x & 0x1f)]
x = x >> 5
i++
}
x = default_rng.u64()
for i < 26 {
buf[i] = rand.ulid_encoding[int(x & 0x1f)]
x = x >> 5
i++
}
res := ''
println(buf)
#res.str = buf.arr.arr.map(String.fromCharCode).join('')
return res
}

View File

@ -112,5 +112,18 @@ pub fn get_host_os() OS {
$if haiku {
return .haiku
}
$if js_node {
return .js_node
}
$if js_freestanding {
return .js_freestanding
}
$if js_browser {
return .js_browser
}
$if js {
return .js_node
}
panic('unknown host OS')
}

View File

@ -171,6 +171,9 @@ pub fn launch_tool(is_verbose bool, tool_name string, args []string) {
}
$if windows {
exit(os.system('"$tool_exe" $tool_args'))
} $else $if js {
// no way to implement os.execvp in JS backend
exit(os.system('$tool_exe $tool_args'))
} $else {
os.execvp(tool_exe, args) or { panic(err) }
}