Skip to content

Commit

Permalink
LibJS: Add initial support for Promises
Browse files Browse the repository at this point in the history
  • Loading branch information
linusg committed Apr 19, 2020
1 parent f38897e commit 7497e04
Show file tree
Hide file tree
Showing 18 changed files with 907 additions and 2 deletions.
1 change: 1 addition & 0 deletions Libraries/LibJS/Forward.h
Expand Up @@ -34,6 +34,7 @@
__JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor) \
__JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor) \
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor) \
__JS_ENUMERATE(Promise, promise, PromisePrototype, PromiseConstructor) \
__JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor)

#define JS_ENUMERATE_ERROR_SUBCLASSES \
Expand Down
27 changes: 27 additions & 0 deletions Libraries/LibJS/Interpreter.cpp
Expand Up @@ -195,6 +195,14 @@ Value Interpreter::call(Function* function, Value this_value, Optional<MarkedVal
return result;
}

Value Interpreter::call(Value value, Value this_value, Optional<MarkedValueList> arguments)
{
if (!value.is_object() || !value.as_object().is_function())
return throw_exception<TypeError>(String::format("%s is not a function", value.to_string().characters()));
auto* function = static_cast<Function*>(&value.as_object());
return call(function, this_value, move(arguments));
}

Value Interpreter::throw_exception(Exception* exception)
{
if (exception->value().is_object() && exception->value().as_object().is_error()) {
Expand Down Expand Up @@ -223,4 +231,23 @@ const GlobalObject& Interpreter::global_object() const
return static_cast<const GlobalObject&>(*m_global_object);
}

void Interpreter::enqueue_promise_job(PromiseReactionJob* job)
{
// FIXME: Actually put job in a queue and execute *soon*, not *immediately*
// Rules are here: https://tc39.es/ecma262/#job
job->execute(*this);
}

void Interpreter::promise_rejection_tracker(Promise* promise, Promise::RejectionOperation operation)
{
switch (operation) {
case Promise::RejectionOperation::Reject:
dbg() << "Promise was rejected without any handlers (reason: " << promise->result() << ")";
break;
case Promise::RejectionOperation::Handle:
dbg() << "A handler was added to an already rejected promise (reason: " << promise->result() << ")";
break;
}
}

}
5 changes: 5 additions & 0 deletions Libraries/LibJS/Interpreter.h
Expand Up @@ -35,6 +35,7 @@
#include <LibJS/Runtime/Exception.h>
#include <LibJS/Runtime/LexicalEnvironment.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/Promise.h>
#include <LibJS/Runtime/Value.h>

namespace JS {
Expand Down Expand Up @@ -102,6 +103,7 @@ class Interpreter {
void exit_scope(const ScopeNode&);

Value call(Function*, Value this_value = {}, Optional<MarkedValueList> arguments = {});
Value call(Value, Value this_value = {}, Optional<MarkedValueList> arguments = {});

CallFrame& push_call_frame()
{
Expand Down Expand Up @@ -160,6 +162,9 @@ class Interpreter {

Value last_value() const { return m_last_value; }

void enqueue_promise_job(PromiseReactionJob*);
void promise_rejection_tracker(Promise*, Promise::RejectionOperation);

private:
Interpreter();

Expand Down
3 changes: 3 additions & 0 deletions Libraries/LibJS/Makefile
Expand Up @@ -37,6 +37,9 @@ OBJS = \
Runtime/ObjectConstructor.o \
Runtime/ObjectPrototype.o \
Runtime/PrimitiveString.o \
Runtime/Promise.o \
Runtime/PromiseConstructor.o \
Runtime/PromisePrototype.o \
Runtime/ScriptFunction.o \
Runtime/Shape.o \
Runtime/StringConstructor.o \
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibJS/Runtime/FunctionConstructor.cpp
Expand Up @@ -71,7 +71,7 @@ Value FunctionConstructor::construct(Interpreter& interpreter)
auto function_expression = parser.parse_function_node<FunctionExpression>();
if (parser.has_errors()) {
// FIXME: The parser should expose parsing error strings rather than just fprintf()'ing them
return Error::create(interpreter.global_object(), "SyntaxError", "");
return SyntaxError::create(interpreter.global_object(), "");
}
return function_expression->execute(interpreter);
}
Expand Down
3 changes: 3 additions & 0 deletions Libraries/LibJS/Runtime/GlobalObject.cpp
Expand Up @@ -49,6 +49,8 @@
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/ObjectConstructor.h>
#include <LibJS/Runtime/ObjectPrototype.h>
#include <LibJS/Runtime/PromiseConstructor.h>
#include <LibJS/Runtime/PromisePrototype.h>
#include <LibJS/Runtime/Shape.h>
#include <LibJS/Runtime/StringConstructor.h>
#include <LibJS/Runtime/StringPrototype.h>
Expand Down Expand Up @@ -104,6 +106,7 @@ void GlobalObject::initialize()
add_constructor("Function", m_function_constructor, *m_function_prototype);
add_constructor("Number", m_number_constructor, *m_number_prototype);
add_constructor("Object", m_object_constructor, *m_object_prototype);
add_constructor("Promise", m_promise_constructor, *m_promise_prototype);
add_constructor("String", m_string_constructor, *m_string_prototype);

#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibJS/Runtime/Object.h
Expand Up @@ -73,6 +73,7 @@ class Object : public Cell {
virtual bool is_function() const { return false; }
virtual bool is_native_function() const { return false; }
virtual bool is_native_property() const { return false; }
virtual bool is_promise() const { return false; }
virtual bool is_string_object() const { return false; }

virtual const char* class_name() const override { return "Object"; }
Expand Down

0 comments on commit 7497e04

Please sign in to comment.