js: add support for Promise.wait() (#12781)
* builtin/js: Change Promise<T,E> to Promise<T> * js: codegen support for Promise.wait() * checker: checker support for Promise.wait()pull/12787/head
parent
7fc9e614a3
commit
b116170735
|
@ -14,46 +14,46 @@ pub fn JS.Promise.race(JS.Array) JS.Promise
|
||||||
|
|
||||||
// The Promise object represents the eventual completion (or failure)
|
// The Promise object represents the eventual completion (or failure)
|
||||||
// of an asynchronous operation and its resulting value.
|
// of an asynchronous operation and its resulting value.
|
||||||
pub struct Promise<T, E> {
|
pub struct Promise<T> {
|
||||||
mut:
|
mut:
|
||||||
promise JS.Promise [noinit]
|
promise JS.Promise [noinit]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn promise_new<T, E>(executor fn (resolve fn (T), reject fn (E))) Promise<T, E> {
|
pub fn promise_new<T>(executor fn (resolve fn (T), reject fn (JS.Any))) Promise<T> {
|
||||||
promise := JS.Promise.prototype.constructor(executor)
|
promise := JS.Promise.prototype.constructor(executor)
|
||||||
return Promise<T, E>{promise}
|
return Promise<T>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p Promise<T, E>) then(on_fullfilled fn (T), on_rejected fn (E)) {
|
pub fn (p Promise<T>) then(on_fullfilled fn (T), on_rejected fn (JS.Any)) {
|
||||||
p.promise.then(on_fullfilled, on_rejected)
|
p.promise.then(on_fullfilled, on_rejected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch method returns a Promise and deals with rejected cases only.
|
// catch method returns a Promise and deals with rejected cases only.
|
||||||
pub fn (p Promise<T, E>) catch(callback fn (error JS.Any)) Promise<T, E> {
|
pub fn (p Promise<T>) catch(callback fn (error JS.Any)) Promise<T> {
|
||||||
promise := p.promise.catch(callback)
|
promise := p.promise.catch(callback)
|
||||||
return Promise<T, E>{promise}
|
return Promise<T>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p Promise<T, E>) finally(callback fn ()) Promise<int, int> {
|
pub fn (p Promise<T>) finally<U>(callback fn ()) Promise<JS.Any> {
|
||||||
promise := p.promise.finally(callback)
|
promise := p.promise.finally(callback)
|
||||||
return Promise<int, int>{promise}
|
return Promise<JS.Any>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject<E> returns promise which was rejected because of specified error
|
// reject<E> returns promise which was rejected because of specified error
|
||||||
pub fn promise_reject<E>(error E) Promise<int, E> {
|
pub fn promise_reject(error JS.Any) Promise<JS.Any> {
|
||||||
promise := JS.Promise.reject(error)
|
promise := JS.Promise.reject(error)
|
||||||
return Promise<int, E>{promise}
|
return Promise<JS.Any>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve<E> returns promise which was resolved with specified value
|
// resolve<E> returns promise which was resolved with specified value
|
||||||
pub fn promise_resolve<T>(result T) Promise<T, int> {
|
pub fn promise_resolve<T>(result T) Promise<T> {
|
||||||
promise := JS.Promise.resolve(error)
|
promise := JS.Promise.resolve(result)
|
||||||
return Promise<T, int>{promise}
|
return Promise<T>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
// race returns returns a promise that fulfills or rejects as soon as one of
|
// 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.
|
// the promises in an iterable fulfills or rejects, with the value or reason from that promise.
|
||||||
pub fn promise_race<T, E>(promises []Promise<T, E>) Promise<T, E> {
|
pub fn promise_race<T>(promises []Promise<T>) Promise<T> {
|
||||||
promises_ := JS.Array.prototype.constructor()
|
promises_ := JS.Array.prototype.constructor()
|
||||||
|
|
||||||
for elem in promises {
|
for elem in promises {
|
||||||
|
@ -61,7 +61,7 @@ pub fn promise_race<T, E>(promises []Promise<T, E>) Promise<T, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
promise := JS.Promise.race(promises_)
|
promise := JS.Promise.race(promises_)
|
||||||
return Promise<T, E>{promise}
|
return Promise<T>{promise}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn JS.Promise.all(JS.Array) JS.Promise
|
pub fn JS.Promise.all(JS.Array) JS.Promise
|
||||||
|
|
|
@ -2044,6 +2044,16 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||||
node.return_type = final_left_sym.info.elem_type
|
node.return_type = final_left_sym.info.elem_type
|
||||||
return node.return_type
|
return node.return_type
|
||||||
}
|
}
|
||||||
|
} else if c.pref.backend.is_js() && left_sym.name.starts_with('Promise<')
|
||||||
|
&& method_name == 'wait' {
|
||||||
|
info := left_sym.info as ast.Struct
|
||||||
|
if node.args.len > 0 {
|
||||||
|
c.error('wait() does not have any arguments', node.args[0].pos)
|
||||||
|
}
|
||||||
|
c.table.cur_fn.has_await = true
|
||||||
|
node.return_type = info.concrete_types[0]
|
||||||
|
node.return_type.set_flag(.optional)
|
||||||
|
return node.return_type
|
||||||
} else if left_sym.kind == .thread && method_name == 'wait' {
|
} else if left_sym.kind == .thread && method_name == 'wait' {
|
||||||
info := left_sym.info as ast.Thread
|
info := left_sym.info as ast.Thread
|
||||||
if node.args.len > 0 {
|
if node.args.len > 0 {
|
||||||
|
|
|
@ -190,9 +190,15 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
||||||
g.gen_expr_to_string(node.left, node.left_type)
|
g.gen_expr_to_string(node.left, node.left_type)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
is_async := node.name == 'wait'
|
||||||
|
&& g.table.get_type_symbol(node.receiver_type).name.starts_with('Promise<')
|
||||||
call_return_is_optional := it.return_type.has_flag(.optional)
|
call_return_is_optional := it.return_type.has_flag(.optional)
|
||||||
if call_return_is_optional {
|
if call_return_is_optional {
|
||||||
|
if is_async {
|
||||||
|
g.writeln('(async function (){')
|
||||||
|
} else {
|
||||||
g.writeln('(function(){')
|
g.writeln('(function(){')
|
||||||
|
}
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
g.writeln('try {')
|
g.writeln('try {')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
|
@ -308,9 +314,15 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
||||||
receiver_type_name = 'array'
|
receiver_type_name = 'array'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_async {
|
||||||
|
g.write('await ')
|
||||||
|
g.expr(it.left)
|
||||||
|
g.write('.promise')
|
||||||
|
} else {
|
||||||
mut name := util.no_dots('${receiver_type_name}_$node.name')
|
mut name := util.no_dots('${receiver_type_name}_$node.name')
|
||||||
|
|
||||||
// name = g.generic_fn_name(node.concrete_types, name, false)
|
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.gen_deref_ptr(it.left_type)
|
g.gen_deref_ptr(it.left_type)
|
||||||
|
@ -322,6 +334,7 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
}
|
||||||
|
|
||||||
if call_return_is_optional {
|
if call_return_is_optional {
|
||||||
// end unwrap
|
// end unwrap
|
||||||
|
@ -406,6 +419,7 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
|
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
|
@ -589,7 +603,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) {
|
||||||
}
|
}
|
||||||
name = g.js_name(name)
|
name = g.js_name(name)
|
||||||
|
|
||||||
// name = g.generic_fn_name(g.table.cur_concrete_types, name, true)
|
name = g.generic_fn_name(g.cur_concrete_types, name, true)
|
||||||
if name in parser.builtin_functions {
|
if name in parser.builtin_functions {
|
||||||
name = 'builtin__$name'
|
name = 'builtin__$name'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue