js: implement more functions for JS backend (#12167)
							parent
							
								
									ade5774313
								
							
						
					
					
						commit
						d373eba79b
					
				|  | @ -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)') | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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') | ||||
| } | ||||
|  |  | |||
|  | @ -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) } | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue