mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:57:35 +00:00
Spreadsheet: Use the LibJS bytecode VM
This commit is contained in:
parent
acd366eddd
commit
fcc72a787b
6 changed files with 38 additions and 35 deletions
|
@ -158,7 +158,7 @@ JS::Value Cell::js_data()
|
|||
if (m_kind == Formula)
|
||||
return m_evaluated_data;
|
||||
|
||||
auto& vm = m_sheet->interpreter().vm();
|
||||
auto& vm = m_sheet->vm();
|
||||
return JS::PrimitiveString::create(vm, m_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ JS::ThrowCompletionOr<DeprecatedString> StringCell::display(Cell& cell, CellType
|
|||
|
||||
JS::ThrowCompletionOr<JS::Value> StringCell::js_value(Cell& cell, CellTypeMetadata const& metadata) const
|
||||
{
|
||||
auto& vm = cell.sheet().interpreter().vm();
|
||||
auto& vm = cell.sheet().vm();
|
||||
auto string = TRY(display(cell, metadata));
|
||||
return JS::PrimitiveString::create(vm, string);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
#include <AK/TemporaryChange.h>
|
||||
#include <AK/URL.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Bytecode/Interpreter.h>
|
||||
#include <LibJS/Heap/DeferGC.h>
|
||||
#include <LibJS/Parser.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
|
@ -40,10 +41,13 @@ Sheet::Sheet(StringView name, Workbook& workbook)
|
|||
|
||||
Sheet::Sheet(Workbook& workbook)
|
||||
: m_workbook(workbook)
|
||||
, m_interpreter(JS::Interpreter::create<SheetGlobalObject>(m_workbook.vm(), *this))
|
||||
, m_vm(workbook.vm())
|
||||
, m_root_execution_context(JS::create_simple_execution_context<SheetGlobalObject>(m_workbook.vm(), *this))
|
||||
{
|
||||
JS::DeferGC defer_gc(m_workbook.vm().heap());
|
||||
m_global_object = static_cast<SheetGlobalObject*>(&m_interpreter->realm().global_object());
|
||||
auto& vm = m_workbook.vm();
|
||||
JS::DeferGC defer_gc(vm.heap());
|
||||
auto& realm = *m_root_execution_context->realm;
|
||||
m_global_object = static_cast<SheetGlobalObject*>(&realm.global_object());
|
||||
global_object().define_direct_property("workbook", m_workbook.workbook_object(), JS::default_attributes);
|
||||
global_object().define_direct_property("thisSheet", &global_object(), JS::default_attributes); // Self-reference is unfortunate, but required.
|
||||
|
||||
|
@ -52,7 +56,7 @@ Sheet::Sheet(Workbook& workbook)
|
|||
auto file_or_error = Core::File::open(runtime_file_path, Core::File::OpenMode::Read);
|
||||
if (!file_or_error.is_error()) {
|
||||
auto buffer = file_or_error.value()->read_until_eof().release_value_but_fixme_should_propagate_errors();
|
||||
auto script_or_error = JS::Script::parse(buffer, interpreter().realm(), runtime_file_path);
|
||||
auto script_or_error = JS::Script::parse(buffer, realm, runtime_file_path);
|
||||
if (script_or_error.is_error()) {
|
||||
warnln("Spreadsheet: Failed to parse runtime code");
|
||||
for (auto& error : script_or_error.error()) {
|
||||
|
@ -60,14 +64,14 @@ Sheet::Sheet(Workbook& workbook)
|
|||
warnln("SyntaxError: {}", error.to_deprecated_string());
|
||||
}
|
||||
} else {
|
||||
auto result = interpreter().run(script_or_error.value());
|
||||
auto result = vm.bytecode_interpreter().run(script_or_error.value());
|
||||
if (result.is_error()) {
|
||||
warnln("Spreadsheet: Failed to run runtime code:");
|
||||
auto thrown_value = *result.throw_completion().value();
|
||||
warn("Threw: {}", MUST(thrown_value.to_string_without_side_effects()));
|
||||
if (thrown_value.is_object() && is<JS::Error>(thrown_value.as_object())) {
|
||||
auto& error = static_cast<JS::Error const&>(thrown_value.as_object());
|
||||
warnln(" with message '{}'", error.get_without_side_effects(interpreter().vm().names.message));
|
||||
warnln(" with message '{}'", error.get_without_side_effects(vm.names.message));
|
||||
for (auto& traceback_frame : error.traceback()) {
|
||||
auto& function_name = traceback_frame.function_name;
|
||||
auto& source_range = traceback_frame.source_range();
|
||||
|
@ -81,11 +85,6 @@ Sheet::Sheet(Workbook& workbook)
|
|||
}
|
||||
}
|
||||
|
||||
JS::Interpreter& Sheet::interpreter() const
|
||||
{
|
||||
return const_cast<JS::Interpreter&>(*m_interpreter);
|
||||
}
|
||||
|
||||
size_t Sheet::add_row()
|
||||
{
|
||||
return m_rows++;
|
||||
|
@ -168,13 +167,13 @@ JS::ThrowCompletionOr<JS::Value> Sheet::evaluate(StringView source, Cell* on_beh
|
|||
auto name = on_behalf_of ? on_behalf_of->name_for_javascript(*this) : "cell <unknown>"sv;
|
||||
auto script_or_error = JS::Script::parse(
|
||||
source,
|
||||
interpreter().realm(),
|
||||
realm(),
|
||||
name);
|
||||
|
||||
if (script_or_error.is_error())
|
||||
return interpreter().vm().throw_completion<JS::SyntaxError>(TRY_OR_THROW_OOM(interpreter().vm(), script_or_error.error().first().to_string()));
|
||||
return vm().throw_completion<JS::SyntaxError>(TRY_OR_THROW_OOM(vm(), script_or_error.error().first().to_string()));
|
||||
|
||||
return interpreter().run(script_or_error.value());
|
||||
return vm().bytecode_interpreter().run(script_or_error.value());
|
||||
}
|
||||
|
||||
Cell* Sheet::at(StringView name)
|
||||
|
@ -425,7 +424,7 @@ RefPtr<Sheet> Sheet::from_json(JsonObject const& object, Workbook& workbook)
|
|||
cell = make<Cell>(obj.get_deprecated_string("value"sv).value_or({}), position, *sheet);
|
||||
break;
|
||||
case Cell::Formula: {
|
||||
auto& vm = sheet->interpreter().vm();
|
||||
auto& vm = sheet->vm();
|
||||
auto value_or_error = JS::call(vm, parse_function, json, JS::PrimitiveString::create(vm, obj.get_deprecated_string("value"sv).value_or({})));
|
||||
if (value_or_error.is_error()) {
|
||||
warnln("Failed to load previous value for cell {}, leaving as undefined", position.to_cell_identifier(sheet));
|
||||
|
@ -557,10 +556,9 @@ JsonObject Sheet::to_json() const
|
|||
JsonObject data;
|
||||
data.set("kind", it.value->kind() == Cell::Kind::Formula ? "Formula" : "LiteralString");
|
||||
if (it.value->kind() == Cell::Formula) {
|
||||
auto& vm = interpreter().vm();
|
||||
data.set("source", it.value->data());
|
||||
auto json = interpreter().realm().global_object().get_without_side_effects("JSON");
|
||||
auto stringified_or_error = JS::call(vm, json.as_object().get_without_side_effects("stringify").as_function(), json, it.value->evaluated_data());
|
||||
auto json = realm().global_object().get_without_side_effects("JSON");
|
||||
auto stringified_or_error = JS::call(vm(), json.as_object().get_without_side_effects("stringify").as_function(), json, it.value->evaluated_data());
|
||||
VERIFY(!stringified_or_error.is_error());
|
||||
data.set("value", stringified_or_error.release_value().to_string_without_side_effects().release_value_but_fixme_should_propagate_errors().to_deprecated_string());
|
||||
} else {
|
||||
|
@ -702,8 +700,8 @@ JsonObject Sheet::gather_documentation() const
|
|||
dbgln("Sheet::gather_documentation(): Failed to parse the documentation for '{}'!", it.key.to_display_string());
|
||||
};
|
||||
|
||||
for (auto& it : interpreter().realm().global_object().shape().property_table())
|
||||
add_docs_from(it, interpreter().realm().global_object());
|
||||
for (auto& it : realm().global_object().shape().property_table())
|
||||
add_docs_from(it, realm().global_object());
|
||||
|
||||
for (auto& it : global_object().shape().property_table())
|
||||
add_docs_from(it, global_object());
|
||||
|
|
|
@ -127,7 +127,6 @@ public:
|
|||
}
|
||||
|
||||
JS::ThrowCompletionOr<JS::Value> evaluate(StringView, Cell* = nullptr);
|
||||
JS::Interpreter& interpreter() const;
|
||||
SheetGlobalObject& global_object() const { return *m_global_object; }
|
||||
|
||||
Cell*& current_evaluated_cell() { return m_current_cell_being_evaluated; }
|
||||
|
@ -149,6 +148,9 @@ public:
|
|||
|
||||
DeprecatedString generate_inline_documentation_for(StringView function, size_t argument_index);
|
||||
|
||||
JS::Realm& realm() const { return *m_root_execution_context->realm; }
|
||||
JS::VM& vm() const { return realm().vm(); }
|
||||
|
||||
private:
|
||||
explicit Sheet(Workbook&);
|
||||
explicit Sheet(StringView name, Workbook&);
|
||||
|
@ -162,7 +164,8 @@ private:
|
|||
Workbook& m_workbook;
|
||||
mutable JS::GCPtr<SheetGlobalObject> m_global_object;
|
||||
|
||||
NonnullOwnPtr<JS::Interpreter> m_interpreter;
|
||||
NonnullRefPtr<JS::VM> m_vm;
|
||||
NonnullOwnPtr<JS::ExecutionContext> m_root_execution_context;
|
||||
|
||||
Cell* m_current_cell_being_evaluated { nullptr };
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibFileSystemAccessClient/Client.h>
|
||||
#include <LibGUI/TextBox.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibJS/Runtime/GlobalEnvironment.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
||||
namespace Spreadsheet {
|
||||
|
@ -21,19 +22,20 @@ namespace Spreadsheet {
|
|||
Workbook::Workbook(Vector<NonnullRefPtr<Sheet>>&& sheets, GUI::Window& parent_window)
|
||||
: m_sheets(move(sheets))
|
||||
, m_vm(JS::VM::create().release_value_but_fixme_should_propagate_errors())
|
||||
, m_interpreter(JS::Interpreter::create<JS::GlobalObject>(m_vm))
|
||||
, m_interpreter_scope(*m_interpreter)
|
||||
, m_root_execution_context(JS::create_simple_execution_context<JS::GlobalObject>(m_vm))
|
||||
, m_main_execution_context(m_vm->heap())
|
||||
, m_parent_window(parent_window)
|
||||
{
|
||||
m_workbook_object = m_vm->heap().allocate<WorkbookObject>(m_interpreter->realm(), m_interpreter->realm(), *this).release_allocated_value_but_fixme_should_propagate_errors();
|
||||
m_interpreter->realm().global_object().define_direct_property("workbook", workbook_object(), JS::default_attributes);
|
||||
auto& realm = *m_root_execution_context->realm;
|
||||
auto& vm = realm.vm();
|
||||
m_workbook_object = vm.heap().allocate<WorkbookObject>(realm, realm, *this).release_allocated_value_but_fixme_should_propagate_errors();
|
||||
realm.global_object().define_direct_property("workbook", workbook_object(), JS::default_attributes);
|
||||
|
||||
m_main_execution_context.this_value = &m_interpreter->realm().global_object();
|
||||
m_main_execution_context.this_value = &realm.global_object();
|
||||
m_main_execution_context.function_name = "(global execution context)"sv;
|
||||
m_main_execution_context.lexical_environment = &m_interpreter->realm().global_environment();
|
||||
m_main_execution_context.variable_environment = &m_interpreter->realm().global_environment();
|
||||
m_main_execution_context.realm = &m_interpreter->realm();
|
||||
m_main_execution_context.lexical_environment = &realm.global_environment();
|
||||
m_main_execution_context.variable_environment = &realm.global_environment();
|
||||
m_main_execution_context.realm = &realm;
|
||||
m_main_execution_context.is_strict_mode = true;
|
||||
m_vm->push_execution_context(m_main_execution_context);
|
||||
m_vm->enable_default_host_import_module_dynamically_hook();
|
||||
|
|
|
@ -44,8 +44,8 @@ public:
|
|||
private:
|
||||
Vector<NonnullRefPtr<Sheet>> m_sheets;
|
||||
NonnullRefPtr<JS::VM> m_vm;
|
||||
NonnullOwnPtr<JS::Interpreter> m_interpreter;
|
||||
JS::VM::InterpreterExecutionScope m_interpreter_scope;
|
||||
NonnullOwnPtr<JS::ExecutionContext> m_root_execution_context;
|
||||
|
||||
JS::GCPtr<WorkbookObject> m_workbook_object;
|
||||
JS::ExecutionContext m_main_execution_context;
|
||||
GUI::Window& m_parent_window;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue