Skip to content

Commit

Permalink
♻️ metadata, function and promise refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
FurryR committed Feb 1, 2024
1 parent ccff5e2 commit 865613e
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 328 deletions.
51 changes: 30 additions & 21 deletions doc/en-us/definition/builtin.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,48 +68,57 @@ declare class Function {
Here is the definition of `Promise` class.

```typescript
interface Thenable<T> {
then(onFulfilled?: (value: T) => void, onRejected?: (reason: any) => void): void
}
interface PromiseLike<T> implements Thenable<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onFulfilled The callback to execute when the Promise is resolved.
* @param onRejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onFulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>, onRejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onFulfilled The callback to execute when the Promise is resolved.
* @param onRejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(
onFulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>,
onRejected?: (reason: any) => TResult2 | PromiseLike<TResult2>
): PromiseLike<TResult1 | TResult2>
}
/**
* Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
*/
type Awaited<T> = T extends null ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode
T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
F extends ((value: infer V, ...args: infer _) => any) ? // if the argument to `then` is callable, extracts the first argument
Awaited<V> : // recursively unwrap the value
never : // the argument to `then` was not callable
T // non-object or non-thenable
type Awaited<T> = T extends null
? T // special case for `null | undefined` when not in `--strictNullChecks` mode
: T extends object & { then(onfulfilled: infer F, ...args: infer _): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
? F extends (value: infer V, ...args: infer _) => any // if the argument to `then` is callable, extracts the first argument
? Awaited<V> // recursively unwrap the value
: never // the argument to `then` was not callable
: T // non-object or non-thenable
declare class Promise<T> implements PromiseLike<T> {
/**
* @constructor Construct a Promise instance.
* @param executor Executor.
*/
constructor(
executor: (resolve: (value: T | Thenable<T>) => void, reject: (reason?: any) => void) => void
executor: (
resolve: (value: T | PromiseLike<T>) => void,
reject: (reason?: any) => void
) => void
)
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onFulfilled The callback to execute when the Promise is resolved.
* @param onRejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onFulfilled?: ((value: T) => TResult1 | Thenable<TResult1>), onRejected?: (reason: any) => TResult2 | Thenable<TResult2>): Promise<TResult1 | TResult2>
then<TResult1 = T, TResult2 = never>(
onFulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>,
onRejected?: (reason: any) => TResult2 | PromiseLike<TResult2>
): Promise<TResult1 | TResult2>
/**
* Attaches a callback for only the rejection of the Promise.
* @param onRejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onRejected?: ((reason: any) => TResult | Thenable<TResult>)): Promise<T | TResult>;
catch<TResult = never>(
onRejected?: (reason: any) => TResult | PromiseLike<TResult>
): Promise<T | TResult>
/**
* Creates a new rejected promise for the provided reason.
* @param reason The reason the promise was rejected.
Expand All @@ -132,7 +141,7 @@ declare class Promise<T> implements PromiseLike<T> {
* @param value A promise.
* @returns A promise whose internal state matches the provided promise.
*/
static resolve<T>(value: T | Thenable<T>): Promise<Awaited<T>>;
static resolve<T>(value: T | PromiseLike<T>): Promise<Awaited<T>>
}
```

Expand Down
Binary file modified doc/en-us/image/readme/export.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/zh-cn/image/readme/export.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 19 additions & 19 deletions src/core/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ export namespace Global {
/**
* lpp builtin `Boolean` -- constructor of boolean types.
*/
export const Boolean = LppFunction.native((_, args) => {
export const Boolean = LppFunction.native(({ args }) => {
if (args.length < 1) return new LppReturn(new LppConstant(false))
return new LppReturn(new LppConstant(asBoolean(args[0])))
}, new LppObject(new Map()))
/**
* lpp builtin `Number` -- constructor of number types.
*/
export const Number = LppFunction.native((_, args) => {
export const Number = LppFunction.native(({ args }) => {
/**
* Convert args to number.
* @param args Array to convert.
Expand Down Expand Up @@ -67,7 +67,7 @@ export namespace Global {
* lpp builtin `String` -- constructor of string types.
*/
export const String = LppFunction.native(
(_, args) => {
({ args }) => {
/**
* Convert args to string.
* @param args Array to convert.
Expand Down Expand Up @@ -98,7 +98,7 @@ export namespace Global {
* lpp builtin `Array` -- constructor of array types.
*/
export const Array = LppFunction.native(
(_, args) => {
({ args }) => {
/**
* Convert args to Array object.
* @param args Array to convert.
Expand Down Expand Up @@ -130,7 +130,7 @@ export namespace Global {
/**
* lpp builtin `Object` -- constructor of object types.
*/
export const Object = LppFunction.native((_, args) => {
export const Object = LppFunction.native(({ args }) => {
/**
* Convert args to object.
* @param args Array to convert.
Expand All @@ -146,7 +146,7 @@ export namespace Global {
* lpp builtin `Function` -- constructor of function types.
*/
export const Function = LppFunction.native(
(_, args) => {
({ args }) => {
if (args.length < 1)
return new LppReturn(
new LppFunction(() => {
Expand All @@ -161,7 +161,7 @@ export namespace Global {
['prototype', ensureValue(Object.get('prototype'))],
[
'apply',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self instanceof LppFunction) {
let selfArg: LppValue = new LppConstant(null)
let argArray: LppValue[] = []
Expand Down Expand Up @@ -195,7 +195,7 @@ export namespace Global {
* lpp builtin `Promise` -- represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
*/
export const Promise = LppFunction.native(
(self, args) => {
({ self, args }) => {
if (
self instanceof LppPromise &&
args.length > 0 &&
Expand All @@ -205,7 +205,7 @@ export namespace Global {
// TODO: resolve(v: PromiseLike<...>)
const temp = LppPromise.generate((resolve, reject) => {
const res = fn.apply(self, [
new LppFunction((_, args) => {
new LppFunction(({ args }) => {
// resolve
const res = processThenReturn(
new LppReturn(args[0] ?? new LppConstant(null)),
Expand All @@ -214,7 +214,7 @@ export namespace Global {
)
return withValue(res, () => new LppReturn(new LppConstant(null)))
}),
new LppFunction((_, args) => {
new LppFunction(({ args }) => {
reject(args[0] ?? new LppConstant(null))
return new LppReturn(new LppConstant(null))
})
Expand All @@ -230,7 +230,7 @@ export namespace Global {
new Map([
[
'then',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self instanceof LppPromise) {
return new LppReturn(
self.done(
Expand All @@ -245,7 +245,7 @@ export namespace Global {
],
[
'catch',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (
self instanceof LppPromise &&
args.length > 0 &&
Expand All @@ -266,7 +266,7 @@ export namespace Global {
)
Promise.set(
'resolve',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self !== Promise) {
return raise(IllegalInvocationError.construct([]))
}
Expand All @@ -283,7 +283,7 @@ export namespace Global {
)
Promise.set(
'reject',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self !== Promise) {
return raise(IllegalInvocationError.construct([]))
}
Expand All @@ -297,7 +297,7 @@ export namespace Global {
/**
* lpp builtin `Error` -- `Error` objects are thrown when runtime errors occur.
*/
export const Error = LppFunction.native((self, args) => {
export const Error = LppFunction.native(({ self, args }) => {
if (self.instanceof(Error)) {
self.set('value', args[0] ?? new LppConstant(null))
self.set('stack', new LppConstant(null))
Expand All @@ -310,7 +310,7 @@ export namespace Global {
* Lpp builtin `IllegalInvocationError` -- represents an error when trying to called a function with illegal arguments / context.
*/
export const IllegalInvocationError = LppFunction.native(
(self, args) => {
({ self, args }) => {
if (self.instanceof(IllegalInvocationError)) {
const res = Error.apply(self, args)
return withValue(res, v => {
Expand All @@ -327,7 +327,7 @@ export namespace Global {
* Lpp builtin `SyntaxError` -- represents an error when trying to interpret syntactically invalid code.
*/
export const SyntaxError = LppFunction.native(
(self, args) => {
({ self, args }) => {
if (self.instanceof(SyntaxError)) {
const res = Error.apply(self, args)
return withValue(res, v => {
Expand All @@ -344,7 +344,7 @@ export namespace Global {
new Map([
[
'parse',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self !== JSON) {
return raise(IllegalInvocationError.construct([]))
}
Expand All @@ -371,7 +371,7 @@ export namespace Global {
],
[
'stringify',
LppFunction.native((self, args) => {
LppFunction.native(({ self, args }) => {
if (self !== JSON) {
return raise(IllegalInvocationError.construct([]))
}
Expand Down
6 changes: 3 additions & 3 deletions src/core/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@ export function processThenReturn(
returnValue: LppResult,
resolve: (v: LppValue) => void,
reject: (reason: unknown) => void
): undefined | PromiseLike<void> {
): undefined | PromiseLike<undefined> {
if (returnValue instanceof LppReturn) {
const value = returnValue.value
if (!(value instanceof LppConstant) || value.value !== null) {
const then = ensureValue(value.get('then'))
if (then instanceof LppFunction) {
const res = then.apply(value, [
new LppFunction((_, args) => {
new LppFunction(({ args }) => {
// resolve
const res = processThenReturn(
new LppReturn(args[0] ?? new LppConstant(null)),
Expand All @@ -206,7 +206,7 @@ export function processThenReturn(
)
return withValue(res, () => new LppReturn(new LppConstant(null)))
}),
new LppFunction((_, args) => {
new LppFunction(({ args }) => {
// reject
reject(args[0] ?? new LppConstant(null))
return new LppReturn(new LppConstant(null))
Expand Down
Loading

0 comments on commit 865613e

Please sign in to comment.