js: ast.GoExpr support using promises on JS backend (#12749)
parent
c23ebec944
commit
1cb06a2de4
|
@ -1,4 +1,4 @@
|
|||
module promise
|
||||
module builtin
|
||||
|
||||
pub interface JS.Promise {
|
||||
then(onFullfilled JS.Any, onRejected JS.Any)
|
||||
|
@ -19,7 +19,7 @@ mut:
|
|||
promise JS.Promise [noinit]
|
||||
}
|
||||
|
||||
pub fn new<T, E>(executor fn (resolve fn (T), reject fn (E))) Promise<T, E> {
|
||||
pub fn promise_new<T, E>(executor fn (resolve fn (T), reject fn (E))) Promise<T, E> {
|
||||
promise := JS.Promise.prototype.constructor(executor)
|
||||
return Promise<T, E>{promise}
|
||||
}
|
||||
|
@ -40,20 +40,20 @@ pub fn (p Promise<T, E>) finally(callback fn ()) Promise<int, int> {
|
|||
}
|
||||
|
||||
// reject<E> returns promise which was rejected because of specified error
|
||||
pub fn reject<E>(error E) Promise<int, E> {
|
||||
pub fn promise_reject<E>(error E) Promise<int, E> {
|
||||
promise := JS.Promise.reject(error)
|
||||
return Promise<int, E>{promise}
|
||||
}
|
||||
|
||||
// resolve<E> returns promise which was resolved with specified value
|
||||
pub fn resolve<T>(result T) Promise<T, int> {
|
||||
pub fn promise_resolve<T>(result T) Promise<T, int> {
|
||||
promise := JS.Promise.resolve(error)
|
||||
return Promise<T, int>{promise}
|
||||
}
|
||||
|
||||
// race returns returns a promise that fulfills or rejects as soon as one of
|
||||
// the promises in an iterable fulfills or rejects, with the value or reason from that promise.
|
||||
pub fn race<T, E>(promises []Promise<T, E>) Promise<T, E> {
|
||||
pub fn promise_race<T, E>(promises []Promise<T, E>) Promise<T, E> {
|
||||
promises_ := JS.Array.prototype.constructor()
|
||||
|
||||
for elem in promises {
|
|
@ -1,3 +0,0 @@
|
|||
// Promise API wrapper
|
||||
|
||||
module promise
|
|
@ -1,18 +0,0 @@
|
|||
module promise
|
||||
|
||||
fn test_promise() {
|
||||
// TODO: For some reason compiler errors: "error: unknown function: js.promise.new", fix this
|
||||
/*
|
||||
p := new<int, f64>(fn (resolve_ fn (x int), reject_ fn (x f64)) {
|
||||
println('Promise code')
|
||||
assert true
|
||||
resolve_(42)
|
||||
})
|
||||
p.then(fn (val int) {
|
||||
println('resolved')
|
||||
assert val == 42
|
||||
}, fn (fail f64) {
|
||||
println('rejected')
|
||||
assert false
|
||||
})*/
|
||||
}
|
|
@ -830,6 +830,26 @@ pub fn (t &Table) chan_cname(elem_type Type, is_mut bool) string {
|
|||
return 'chan_$elem_type_sym.cname' + suffix
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) promise_name(return_type Type) string {
|
||||
if return_type.idx() == void_type_idx {
|
||||
return 'Promise<JS.Any,JS.Any>'
|
||||
}
|
||||
|
||||
return_type_sym := t.get_type_symbol(return_type)
|
||||
return 'Promise<$return_type_sym.name, JS.Any>'
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) promise_cname(return_type Type) string {
|
||||
if return_type == void_type {
|
||||
return 'Promise_Any_Any'
|
||||
}
|
||||
|
||||
return_type_sym := t.get_type_symbol(return_type)
|
||||
return 'Promise_${return_type_sym.name}_Any'
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) thread_name(return_type Type) string {
|
||||
if return_type.idx() == void_type_idx {
|
||||
|
@ -943,6 +963,30 @@ pub fn (mut t Table) find_or_register_thread(return_type Type) int {
|
|||
return t.register_type_symbol(thread_typ)
|
||||
}
|
||||
|
||||
pub fn (mut t Table) find_or_register_promise(return_type Type) int {
|
||||
name := t.promise_name(return_type)
|
||||
|
||||
cname := t.promise_cname(return_type)
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx
|
||||
}
|
||||
|
||||
promise_type := TypeSymbol{
|
||||
parent_idx: t.type_idxs['Promise']
|
||||
kind: .struct_
|
||||
name: name
|
||||
cname: cname
|
||||
info: Struct{
|
||||
concrete_types: [return_type, t.type_idxs['JS.Any']]
|
||||
}
|
||||
}
|
||||
|
||||
// register
|
||||
return t.register_type_symbol(promise_type)
|
||||
}
|
||||
|
||||
pub fn (mut t Table) find_or_register_array(elem_type Type) int {
|
||||
name := t.array_name(elem_type)
|
||||
// existing
|
||||
|
|
|
@ -2560,7 +2560,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
typ := c.expr(node.args[0].expr)
|
||||
tsym := c.table.get_type_symbol(typ)
|
||||
|
||||
if !tsym.name.starts_with('js.promise.Promise<') {
|
||||
if !tsym.name.starts_with('Promise<') {
|
||||
c.error('JS.await: first argument must be a promise, got `$tsym.name`', node.pos)
|
||||
return ast.void_type
|
||||
}
|
||||
|
@ -5040,7 +5040,12 @@ fn (mut c Checker) go_expr(mut node ast.GoExpr) ast.Type {
|
|||
c.error('method in `go` statement cannot have non-reference mutable receiver',
|
||||
node.call_expr.left.position())
|
||||
}
|
||||
return c.table.find_or_register_thread(ret_type)
|
||||
|
||||
if c.pref.backend.is_js() {
|
||||
return c.table.find_or_register_promise(ret_type)
|
||||
} else {
|
||||
return c.table.find_or_register_thread(ret_type)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) {
|
||||
|
|
|
@ -17,7 +17,7 @@ const (
|
|||
'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'package',
|
||||
'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
||||
'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', 'Number', 'String', 'Boolean',
|
||||
'Array', 'Map', 'document']
|
||||
'Array', 'Map', 'document', 'Promise']
|
||||
// used to generate type structs
|
||||
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64',
|
||||
'int_literal', 'float_literal', 'bool', 'string', 'map', 'array', 'rune', 'any', 'voidptr']
|
||||
|
@ -1679,13 +1679,13 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) {
|
|||
}
|
||||
|
||||
fn (mut g JsGen) gen_go_expr(node ast.GoExpr) {
|
||||
g.writeln('await new Promise(function(resolve){')
|
||||
g.writeln('new _v_Promise({promise: new Promise(function(resolve){')
|
||||
g.inc_indent()
|
||||
g.write('resolve(')
|
||||
g.expr(node.call_expr)
|
||||
g.write(');')
|
||||
g.dec_indent()
|
||||
g.writeln('});')
|
||||
g.writeln('})});')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_import_stmt(it ast.Import) {
|
||||
|
|
Loading…
Reference in New Issue