1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 19:15:07 +00:00

LibJS: Add NativeFunction, a callable wrapper around a C++ lambda

This can be used to implement arbitrary functionality, callable from
JavaScript.

To make this work, I had to change the way CallExpression passes
arguments to the callee. Instead of a HashMap<String, Value>, we now
pass an ordered list of Argument { String name; Value value; }.

This patch includes a native "print(argument)" function. :^)
This commit is contained in:
Andreas Kling 2020-03-12 19:53:31 +01:00
parent cc8e3048bc
commit 7912f33ea0
9 changed files with 129 additions and 17 deletions

View file

@ -27,8 +27,10 @@
#include <AK/Badge.h>
#include <LibJS/AST.h>
#include <LibJS/Interpreter.h>
#include <LibJS/NativeFunction.h>
#include <LibJS/Object.h>
#include <LibJS/Value.h>
#include <stdio.h>
namespace JS {
@ -36,15 +38,20 @@ Interpreter::Interpreter()
: m_heap(*this)
{
m_global_object = heap().allocate<Object>();
m_global_object->put("print", Value(heap().allocate<NativeFunction>([](Vector<Argument> arguments) -> Value {
for (auto& argument : arguments)
printf("%s ", argument.value.to_string().characters());
return js_undefined();
})));
}
Interpreter::~Interpreter()
{
}
Value Interpreter::run(const ScopeNode& scope_node, HashMap<String, Value> scope_variables, ScopeType scope_type)
Value Interpreter::run(const ScopeNode& scope_node, Vector<Argument> arguments, ScopeType scope_type)
{
enter_scope(scope_node, move(scope_variables), scope_type);
enter_scope(scope_node, move(arguments), scope_type);
Value last_value = js_undefined();
for (auto& node : scope_node.children()) {
@ -55,13 +62,12 @@ Value Interpreter::run(const ScopeNode& scope_node, HashMap<String, Value> scope
return last_value;
}
void Interpreter::enter_scope(const ScopeNode& scope_node, HashMap<String, Value> scope_variables, ScopeType scope_type)
void Interpreter::enter_scope(const ScopeNode& scope_node, Vector<Argument> arguments, ScopeType scope_type)
{
HashMap<String, Variable> scope_variables_with_declaration_type;
for (String name : scope_variables.keys()) {
scope_variables_with_declaration_type.set(name, { scope_variables.get(name).value(), DeclarationType::Var });
for (auto& argument : arguments) {
scope_variables_with_declaration_type.set(argument.name, { argument.value, DeclarationType::Var });
}
m_scope_stack.append({ scope_type, scope_node, move(scope_variables_with_declaration_type) });
}