Coder Social home page Coder Social logo

promises-unwrapping's Introduction

Promise Objects

This repository is meant to fully flesh out a subset of the "AP2" promise consensus developed over the last month on es-discuss. In particular, it provides the subset the DOM needs as soon as possible, omitting flatMap for now but building a conceptual foundation that would allow it to be added at a later date.

It is meant to succeed the current DOM Promises spec, and fixes a number of bugs in that spec while also changing some of the exposed APIs and behavior to make it more forward-compatible with the full AP2 consensus.

Record Types for Promise Objects

The Deferred Specification Type

The Deferred type is used to encapsulate newly-created promise objects along with functions that resolve or reject them. Deferred objects are derived by the GetDeferred abstract operation from either the Promise constructor itself or from a constructor that subclasses the Promise constructor. This mechanism allows promise subclasses to install custom resolve and reject behavior by creating constructors that pass appropriate functions to their resolver argument.

Deferreds are Records composed of three named fields:

  • [[Promise]]: the newly-created promise object
  • [[Resolve]]: a function that is presumed to resolve the given promise object
  • [[Reject]]: a function that is presumed to reject the given promise object

The PromiseReaction Specification Type

The PromiseReaction type is used to store information about how a promise should react when it becomes resolved or rejected with a given value. PromiseReaction objects are created by the then method of the Promise prototype, and are used by the ExecutePromiseReaction microtask.

PromiseReactions are Records composed of two named fields:

  • [[Deferred]]: a Deferred record representing a derived promise and the ability to resolve or reject it.
  • [[Handler]]: a function that should be applied to the incoming value, and whose return value will govern what happens to the derived promise.

Abstract Operations for Promise Objects

GetDeferred ( C )

The abstract operation GetDeferred takes a potential constructor function, and attempts to use that constructor function in the fashion of the normal promise constructor to extract resolve and reject functions, returning the constructed promise along with those two functions controlling its state. This is useful to support subclassing, as this operation is generic on any constructor that calls a passed resolver argument in the same way as the Promise constructor. We use it to generalize static methods of the Promise constructor to any subclass.

  1. If IsConstructor(C) is false, throw a TypeError.
  2. Let resolver be a new built-in function object as defined in Deferred Construction Functions.
  3. Let promise be the result of calling the [[Construct]] internal method of C with an argument list containing the single item resolver.
  4. ReturnIfAbrupt(promise).
  5. Let resolve be the value of resolver's [[Resolve]] internal slot.
  6. If IsCallable(resolve) is false, throw a TypeError.
  7. Let reject be the value of resolver's [[Reject]] internal slot.
  8. If IsCallable(reject) is false, throw a TypeError.
  9. Return the Deferred { [[Promise]]: promise, [[Resolve]]: resolve, [[Reject]]: reject }.

IsPromise ( x )

The abstract operation IsPromise checks for the promise brand on an object.

  1. If Type(x) is not Object, return false.
  2. If x does not have a [[PromiseStatus]] internal slot, return false.
  3. If the value of x's [[PromiseStatus]] internal slot is undefined, return false.
  4. Return true.

PromiseReject ( promise, reason )

The abstract operation PromiseReject rejects a promise with a reason.

  1. If the value of promise's internal slot [[PromiseStatus]] is not "unresolved", return.
  2. Let reactions be the value of promise's [[RejectReactions]] internal slot.
  3. Set the value of promise's [[Result]] internal slot to reason.
  4. Set the value of promise's [[ResolveReactions]] internal slot to undefined.
  5. Set the value of promise's [[RejectReactions]] internal slot to undefined.
  6. Set the value of promise's [[PromiseStatus]] internal slot to "has-rejection".
  7. Return the result of calling TriggerPromiseReactions(reactions, reason).

PromiseResolve ( promise, resolution )

The abstract operation PromiseResolve resolves a promise with a value.

  1. If the value of promise's internal slot [[PromiseStatus]] is not "unresolved", return.
  2. Let reactions be the value of promise's [[ResolveReactions]] internal slot.
  3. Set the value of promise's [[Result]] internal slot to resolution.
  4. Set the value of promise's [[ResolveReactions]] internal slot to undefined.
  5. Set the value of promise's [[RejectReactions]] internal slot to undefined.
  6. Set the value of promise's [[PromiseStatus]] internal slot to "has-resolution".
  7. Return the result of calling TriggerPromiseReactions(reactions, resolution).

TriggerPromiseReactions ( reactions, argument )

The abstract operation TriggerPromiseReactions takes a collection of functions to trigger in the next microtask, and calls them, passing each the given argument. Typically, these reactions will modify a previously-returned promise, possibly calling in to a user-supplied handler before doing so.

  1. Repeat for each reaction in reactions, in original insertion order
    1. Call QueueMicrotask(ExecutePromiseReaction, (reaction, argument)).
  2. Return.

UpdateDeferredFromPotentialThenable ( x, deferred )

The abstract operation UpdateDeferredFromPotentialThenable takes a value x and tests if it is a thenable. If so, it tries to use x's then method to resolve deferred. Otherwise, it returns "not a thenable".

  1. If Type(x) is not Object, return "not a thenable".
  2. Let then be the result of calling Get(x, "then").
  3. If then is an abrupt completion,
    1. Let rejectResult be the result of calling the [[Call]] internal method of deferred.[[Reject]] with undefined as thisArgument and a List containing then.[[value]] as argumentsList.
    2. ReturnIfAbrupt(rejectResult).
    3. Return.
  4. Let then be then.[[value]].
  5. If IsCallable(then) is false, return "not a thenable".
  6. Let thenCallResult be the result of calling the [[Call]] internal method of then passing x as thisArgument and a List containing deferred.[[Resolve]] and deferred.[[Reject]] as argumentsList.
  7. If thenCallResult is an abrupt completion,
    1. Let rejectResult be the result of calling the [[Call]] internal method of deferred.[[Reject]] with undefined as thisArgument and a List containing thenCallResult.[[value]] as argumentsList.
    2. ReturnIfAbrupt(rejectResult).

Built-in Functions for Promise Objects

Deferred Construction Functions

A deferred construction function is an anonymous function that stores its arguments for later use in constructing a Deferred record.

Each deferred construction function has [[Resolve]] and [[Reject]] internal slots.

When a deferred construction function F is called with arguments resolve and reject, the following steps are taken:

  1. Set F's [[Resolve]] internal slot to resolve.
  2. Set F's [[Reject]] internal slot to reject.
  3. Return.

Identity Functions

An identity function simply returns its input.

When an identity function is called with argument x, the following steps are taken:

  1. Return x.

Promise.all Countdown Functions

A Promise.all countdown function is an anonymous function that handles fulfillment of any promises passed to the all method of the Promise constructor.

Each Promise.all countdown function has [[Index]], [[Values]], [[Deferred]], and [[CountdownHolder]] internal slots.

When a Promise.all countdown function F is called with argument x, the following steps are taken:

  1. Let index be the value of F's [[Index]] internal slot.
  2. Let values be the value of F's [[Values]] internal slot.
  3. Let deferred be the value of F's [[Deferred]] internal slot.
  4. Let countdownHolder be the value of F's [[CountdownHolder]] internal slot.
  5. Let result be the result of calling the [[DefineOwnProperty]] internal method of values with arguments index and Property Descriptor { [[Value]]: x, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  6. RejectIfAbrupt(result, deferred).
  7. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] - 1.
  8. If countdownHolder.[[Countdown]] is 0,
    1. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]] with undefined as thisArgument and a List containing values as argumentsList.
  9. Return.

Promise Resolution Handler Functions

A promise resolution handler function is an anonymous function that has the ability to handle a promise being resolved, by "unwrapping" any incoming values until they are no longer promises or thenables and can be passed to the appropriate fulfillment handler.

Each promise resolution handler function has [[Promise]], [[FulfillmentHandler]], and [[RejectionHandler]] internal slots.

When a promise resolution handler function F is called with argument x, the following steps are taken:

  1. Let promise be the value of F's [[Promise]] internal slot.
  2. Let fulfillmentHandler be the value of F's [[FulfillmentHandler]] internal slot.
  3. Let rejectionHandler be the value of F's [[RejectionHandler]] internal slot.
  4. If SameValue(x, promise) is true,
    1. Let selfResolutionError be a newly-created TypeError object.
    2. Return the result of calling the [[Call]] internal method of rejectionHandler with undefined as thisArgument and a List containing selfResolutionError as argumentsList.
  5. Let C be the value of promise's [[PromiseConstructor]] internal slot.
  6. If IsPromise(x) is true,
    1. Let xConstructor be the value of x's [[PromiseConstructor]] internal slot.
    2. If SameValue(xConstructor, C) is true, return the result of calling Invoke(x, "then", (fulfillmentHandler, rejectionHandler)).
  7. Let deferred be the result of calling GetDeferred(C).
  8. ReturnIfAbrupt(deferred).
  9. Let updateResult be the result of calling UpdateDeferredFromPotentialThenable(x, deferred).
  10. ReturnIfAbrupt(updateResult).
  11. If updateResult is not "not a thenable", return the result of calling Invoke(deferred.[[Promise]], "then", (fulfillmentHandler, rejectionHandler)).
  12. Return the result of calling the [[Call]] internal method of fulfillmentHandler with undefined as thisArgument and a List containing x as argumentsList.

Reject Promise Functions

A reject promise function is an anonymous function that has the ability to reject a promise with a given reason.

Each reject promise function has a [[Promise]] internal slot.

When a reject promise function F is called with argument reason, the following steps are taken:

  1. Let promise be the value of F's [[Promise]] internal slot.
  2. Return the result of calling PromiseReject(promise, reason).

Resolve Promise Functions

A resolve promise function is an anonymous function that has the ability to resolve a promise with a given resolution.

Each resolve promise function has a [[Promise]] internal slot.

When a resolve promise function F is called with argument resolution, the following steps are taken:

  1. Let promise be the value of F's [[Promise]] internal slot.
  2. Return the result of calling PromiseResolve(promise, resolution).

Thrower Functions

A thrower function simply throws its input.

When a thrower function is called with argument e, the following steps are taken:

  1. Return Completion{[[type]]: throw, [[value]]: e, [[target]]:empty}.

Microtasks for Promise Objects

Microtask ExecutePromiseReaction( reaction, argument )

The microtask ExecutePromiseReaction applies the appropriate handler to the incoming value, and uses the handler's return value to resolve or reject the derived promise associated with that handler.

  1. Let deferred be reaction.[[Deferred]].
  2. Let handler be reaction.[[Handler]].
  3. Let handlerResult be the result of calling the [[Call]] internal method of handler passing undefined as thisArgument and a List containing argument as argumentsList.
  4. If handlerResult is an abrupt completion, return the result of calling the [[Call]] internal method of deferred.[[Reject]] passing undefined as thisArgument and a List containing handlerResult.[[value]] as argumentsList.
  5. Let handlerResult be handlerResult.[[value]].
  6. If SameValue(handlerResult, deferred.[[Promise]]) is true,
    1. Let selfResolutionError be a newly-created TypeError object.
    2. Return the result of calling the [[Call]] internal method of deferred.[[Reject]] passing undefined as thisArgument and a List containing selfResolutionError as argumentsList
  7. Let updateResult be the result of calling UpdateDeferredFromPotentialThenable(handlerResult, deferred).
  8. ReturnIfAbrupt(updateResult).
  9. If updateResult is "not a thenable",
    1. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]] passing undefined as thisArgument and a List containing handlerResult as argumentsList.

The Promise Constructor

The Promise constructor is the %Promise% intrinsic object and the initial value of the Promise property of the global object. When Promise is called as a function rather than as a constructor, it initializes its this value with the internal state necessary to support the Promise.prototype methods.

The Promise constructor is designed to be subclassable. It may be used as the value of an extends clause of a class declaration. Subclass constructors that intended to inherit the specified Promise behavior must include a super call to the Promise constructor.

Promise ( resolver )

  1. Let promise be the this value.
  2. If Type(promise) is not Object, then throw a TypeError exception.
  3. If promise does not have a [[PromiseStatus]] internal slot, then throw a TypeError exception.
  4. If promise's [[PromiseStatus]] internal slot is not undefined, then throw a TypeError exception.
  5. If IsCallable(resolver) is false, then throw a TypeError exception.
  6. Set promise's [[PromiseStatus]] internal slot to "unresolved".
  7. Set promise's [[ResolveReactions]] internal slot to a new empty List.
  8. Set promise's [[RejectReactions]] internal slot to a new empty List.
  9. Let resolve be a new built-in function object as defined in Resolve Promise Functions.
  10. Set the [[Promise]] internal slot of resolve to promise.
  11. Let reject be a new built-in function object as defined in Reject Promise Functions.
  12. Set the [[Promise]] internal slot of reject to promise.
  13. Let result be the result of calling the [[Call]] internal method of resolver with undefined as thisArgument and a List containing resolve and reject as argumentsList.
  14. If result is an abrupt completion, call PromiseReject(promise, result.[[value]]).
  15. Return promise.

new Promise ( ... argumentsList )

When Promise is called as part of a new expression it is a constructor: it initialises a newly created object.

Promise called as part of a new expression with argument list argumentsList performs the following steps:

  1. Let F be the Promise function object on which the new operator was applied.
  2. Let argumentsList be the argumentsList argument of the [[Construct]] internal method that was invoked by the new operator.
  3. Return the result of OrdinaryConstruct(F, argumentsList).

If Promise is implemented as an ordinary function object, its [[Construct]] internal method will perform the above steps.

Properties of the Promise Constructor

Promise [ @@create ] ( )

  1. Let F be the this value.
  2. Let obj be the result of calling OrdinaryCreateFromConstructor(constructor, "%PromisePrototype%", ([[PromiseStatus]], [[PromiseConstructor]], [[Result]], [[ResolveReactions]], [[RejectReactions]])).
  3. Set obj's [[PromiseConstructor]] internal slot to F.
  4. Return obj.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

Promise.all ( iterable )

all returns a new promise which is fulfilled with an array of fulfillment values for the passed promises, or rejects with the reason of the first passed promise that rejects. It casts all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let deferred be the result of calling GetDeferred(C).
  3. ReturnIfAbrupt(deferred).
  4. Let iterator be the result of calling GetIterator(iterable).
  5. RejectIfAbrupt(iterator, deferred).
  6. Let values be the result of calling ArrayCreate(0).
  7. Let countdownHolder be Record { [[Countdown]]: 0 }.
  8. Let index be 0.
  9. Repeat
    1. Let next be the result of calling IteratorStep(iterator).
    2. RejectIfAbrupt(next, deferred).
    3. If next is false,
      1. If index is 0,
        1. Let resolveResult be the result of calling the [[Call]] internal method of deferred.[[Resolve]] with undefined as thisArgument and a List containing values as argumentsList.
        2. ReturnIfAbrupt(resolveResult).
      2. Return deferred.[[Promise]].
    4. Let nextValue be the result of calling IteratorValue(next).
    5. RejectIfAbrupt(nextValue, deferred).
    6. Let nextPromise be the result of calling Invoke(C, "cast", (nextValue)).
    7. RejectIfAbrupt(nextPromise, deferred).
    8. Let countdownFunction be a new built-in function object as defined in Promise.all Countdown Functions.
    9. Set the [[Index]] internal slot of countdownFunction to index.
    10. Set the [[Values]] internal slot of countdownFunction to values.
    11. Set the [[Deferred]] internal slot of countdownFunction to deferred.
    12. Set the [[CountdownHolder]] internal slot of countdownFunction to countdownHolder.
    13. Let result be the result of calling Invoke(nextPromise, "then", (countdownFunction, deferred.[[Reject]])).
    14. RejectIfAbrupt(result, deferred).
    15. Set index to index + 1.
    16. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] + 1.

Note: The all function is an intentionally generic utility method; it does not require that its this value be the Promise constructor. Therefore, it can be transferred to or inherited by any other constructors that may be called with a single function argument.

Promise.cast ( x )

cast coerces its argument to a promise, or returns the argument if it is already a promise.

  1. Let C be the this value.
  2. If IsPromise(x) is true,
    1. Let constructor be the value of x's [[PromiseConstructor]] internal slot.
    2. If SameValue(constructor, C) is true, return x.
  3. Let deferred be the result of calling GetDeferred(C).
  4. ReturnIfAbrupt(deferred).
  5. Let resolveResult be the result of calling the [[Call]] internal method of deferred.[[Resolve]] with undefined as thisArgument and a List containing x as argumentsList.
  6. ReturnIfAbrupt(resolveResult).
  7. Return deferred.[[Promise]].

Note: The cast function is an intentionally generic utility method; it does not require that its this value be the Promise constructor. Therefore, it can be transferred to or inherited by any other constructors that may be called with a single function argument.

Promise.race ( iterable )

race returns a new promise which is settled in the same way as the first passed promise to settle. It casts all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let deferred be the result of calling GetDeferred(C).
  3. ReturnIfAbrupt(deferred).
  4. Let iterator be the result of calling GetIterator(iterable).
  5. RejectIfAbrupt(iterator, deferred).
  6. Repeat
    1. Let next be the result of calling IteratorStep(iterator).
    2. RejectIfAbrupt(next, deferred).
    3. If next is false, return deferred.[[Promise]].
    4. Let nextValue be the result of calling IteratorValue(next).
    5. RejectIfAbrupt(nextValue, deferred).
    6. Let nextPromise be the result of calling Invoke(C, "cast", (nextValue)).
    7. RejectIfAbrupt(nextPromise, deferred).
    8. Let result be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])).
    9. RejectIfAbrupt(result, deferred).

Note: The race function is an intentionally generic utility method; it does not require that its this value be the Promise constructor. Therefore, it can be transferred to or inherited by any other constructors that may be called with a single function argument.

Promise.reject ( r )

reject returns a new promise rejected with the passed argument.

  1. Let C be the this value.
  2. Let deferred be the result of calling GetDeferred(C).
  3. ReturnIfAbrupt(deferred).
  4. Let rejectResult be the result of calling the [[Call]] internal method of deferred.[[Reject]] with undefined as thisArgument and a List containing r as argumentsList.
  5. ReturnIfAbrupt(rejectResult).
  6. Return deferred.[[Promise]].

Note: The reject function is an intentionally generic factory method; it does not require that its this value be the Promise constructor. Therefore, it can be transferred to or inherited by any other constructors that may be called with a single function argument.

Promise.resolve ( x )

resolve returns a new promise resolved with the passed argument.

  1. Let C be the this value.
  2. Let deferred be the result of calling GetDeferred(C).
  3. ReturnIfAbrupt(deferred).
  4. Let resolveResult be the result of calling the [[Call]] internal method of deferred.[[Resolve]] with undefined as thisArgument and a List containing x as argumentsList.
  5. ReturnIfAbrupt(resolveResult).
  6. Return deferred.[[Promise]].

Note: The resolve function is an intentionally generic factory method; it does not require that its this value be the Promise constructor. Therefore, it can be transferred to or inherited by any other constructors that may be called with a single function argument.

Properties of the Promise Prototype Object

The Promise prototype object is itself an ordinary object. It is not a Promise instance and does not have any of the promise instances' internal slots, such as [[PromiseStatus]].

The value of the [[Prototype]] internal slot of the Promise prototype object is the standard built-in Object prototype object.

Promise.prototype.constructor

The initial value of Promise.prototype.constructor is the built-in Promise constructor.

Promise.prototype.catch ( onRejected )

  1. Let promise be the this value.
  2. Return the result of calling Invoke(promise, "then", (undefined, onRejected)).

Note: The catch function is intentionally generic; it does not require that its this value be a Promise object. Therefore, it can be transferred to other kinds of objects for use as a method.

Promise.prototype.then ( onFulfilled , onRejected )

  1. Let promise be the this value.
  2. If IsPromise(promise) is false, throw a TypeError exception.
  3. Let C be the result of calling Get(promise, "constructor").
  4. ReturnIfAbrupt(C).
  5. Let deferred be the result of calling GetDeferred(C).
  6. ReturnIfAbrupt(deferred).
  7. Let rejectionHandler be a new built-in function object as defined in Thrower Functions.
  8. If IsCallable(onRejected), set rejectionHandler to onRejected.
  9. Let fulfillmentHandler be a new built-in function object as defined in Identity Functions.
  10. If IsCallable(onFulfilled), set fulfillmentHandler to onFulfilled.
  11. Let resolutionHandler be a new built-in function object as defined in Promise Resolution Handler Functions.
  12. Set the [[Promise]] internal slot of resolutionHandler to promise.
  13. Set the [[FulfillmentHandler]] internal slot of resolutionHandler to fulfillmentHandler.
  14. Set the [[RejectionHandler]] internal slot of resolutionHandler to rejectionHandler.
  15. Let resolveReaction be the PromiseReaction { [[Deferred]]: deferred, [[Handler]]: resolutionHandler }.
  16. Let rejectReaction be the PromiseReaction { [[Deferred]]: deferred, [[Handler]]: rejectionHandler }.
  17. If the value of promise's [[PromiseStatus]] internal slot is "unresolved",
    1. Append resolveReaction as the last element of promise's [[ResolveReactions]] internal slot.
    2. Append rejectReaction as the last element of promise's [[RejectReactions]] internal slot.
  18. If the value of promise's [[PromiseStatus]] internal slot is "has-resolution",
    1. Let resolution be the value of promise's [[Result]] internal slot.
    2. Call QueueMicrotask(ExecutePromiseReaction, (resolveReaction, resolution)).
  19. If the value of promise's [[PromiseStatus]] internal slot is "has-rejection",
    1. Let reason be the value of promise's [[Result]] internal slot.
    2. Call QueueMicrotask(ExecutePromiseReaction, (rejectReaction, reason)).
  20. Return deferred.[[Promise]].

Note: The then function is not generic. If the this value is not an object with an [[PromiseStatus]] internal slot initialized to true, a TypeError exception is immediately thrown when it is called.

Properties of Promise Instances

Promise instances are ordinary objects that inherit properties from the Promise prototype (the intrinsic, %PromisePrototype%). Promise instances are initially created with the internal slots described in this table.

Internal Slots of Promise Instances
Internal Slot Name Description
[[PromiseStatus]] A string value that governs how a promise will react to incoming calls to its then method. The possible values are: "unresolved", "has-resolution", and "has-rejection".
[[PromiseConstructor]] The function object that was used to construct this promise. Checked by the cast method of the Promise constructor.
[[Result]] The value with which the promise has been resolved or rejected, if any. Only meaningful if [[PromiseStatus]] is not "unresolved".
[[ResolveReactions]] A List of PromiseReactions to be processed when/if the promise transitions from being unresolved to having a resolution.
[[RejectReactions]] A List of PromiseReactions to be processed when/if the promise transitions from being unresolved to having a rejection.

Deltas to Other Areas of the Spec

???

Somewhere in the spec—I'm not sure where—add the following abstract operation:

QueueMicrotask ( microtask, argumentsList )

The abstract operation QueueMicrotask performs the implementation-specific operation of "queueing a microtask" to run the given microtask steps. The only important invariant required by this specification is that the microtask steps must be run with an empty execution context stack. Once this is guaranteed,

  1. Run the steps specified by microtask, passing argumentsList.

Well-Known Intrinsic Objects Table

Add the following rows:

%Promise% The initial value of the global object property named "Promise".
%PromisePrototype% The initial value of the "prototype" data property of the intrinsic %Promise%.

The Completion Record Specification Type

Add the following section:

RejectIfAbrupt

Algorithm steps that say

  1. RejectIfAbrupt(argument, deferred).

mean the same things as:

  1. If argument is an abrupt completion,
    1. Let rejectResult be the result of calling the [[Call]] internal method of deferred.[[Reject]] with undefined as thisArgument and a List containing argument.[[value]] as argumentsList.
    2. ReturnIfAbrupt(rejectResult).
    3. Return deferred.[[Promise]].
  2. Else if argument is a Completion Record, then let argument be argument.[[value]].

CC0
To the extent possible under law, Domenic Denicola has waived all copyright and related or neighboring rights to promises-unwrapping.

This work is published from:
<span property="vcard:Country" datatype="dct:ISO3166" content="US" about="http://domenicdenicola.com">
  United States
</span>.

promises-unwrapping's People

Contributors

annevk avatar domenic avatar forbeslindesay avatar mounirlamouri avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.