Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
build: [release, debug]
build: [release, debug, weval]
os: [ubuntu-latest]
outputs:
SM_TAG_EXISTS: ${{ steps.check-sm-release.outputs.SM_TAG_EXISTS }}
Expand Down
2 changes: 2 additions & 0 deletions builtins/web/crypto/uuid.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "uuid.h"
#include "host_api.h"

#include <fmt/format.h>



namespace builtins::web::crypto {
Expand Down
2 changes: 2 additions & 0 deletions builtins/web/event/event-target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ template <typename T> struct GCPolicy<RefPtr<T>> {
}
return true;
}
static constexpr bool mightBeInNursery() { return false; }
static bool isTenured(const RefPtr<T> & /*unused*/) { return true; }
};

} // namespace JS
Expand Down
4 changes: 2 additions & 2 deletions cmake/spidermonkey.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(SM_TAG FIREFOX_140_0_4_RELEASE_STARLING)
set(SM_TAG FIREFOX_147_0_4_RELEASE_STARLING)

include("manage-git-source")

Expand Down Expand Up @@ -59,7 +59,7 @@ else()

manage_git_source(
NAME spidermonkey
REPO_URL https://github.com/bytecodealliance/firefox.git
REPO_URL https://github.com/andreiltd/firefox.git
TAG ${SM_TAG}
SOURCE_DIR ${SM_SOURCE_DIR}
)
Expand Down
1 change: 1 addition & 0 deletions runtime/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <fmt/format.h>
#include <utility>

#ifdef MEM_STATS
Expand Down
132 changes: 81 additions & 51 deletions runtime/script_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
#include <cstdio>
#include <js/CompilationAndEvaluation.h>
#include <js/MapAndSet.h>
#include <js/ScriptPrivate.h>
#include <js/Value.h>
#include <jsfriendapi.h>
#include <sys/stat.h>

namespace {

api::Engine* ENGINE;
ScriptLoader* SCRIPT_LOADER;
api::Engine *ENGINE;
ScriptLoader *SCRIPT_LOADER;
bool MODULE_MODE = true;
std::string BASE_PATH;

Expand All @@ -29,16 +30,14 @@ namespace ScriptLoaderErrors {
DEF_ERR(ModuleLoadingError, JSEXN_REFERENCEERR,
"Error loading module \"{0}\" (resolved path \"{1}\"): {2}", 3)
DEF_ERR(BuiltinModuleExists, JSEXN_TYPEERR, "Builtin module \"{0}\" already exists", 1)
};
}; // namespace ScriptLoaderErrors

class AutoCloseFile {
FILE* file;
FILE *file;

public:
explicit AutoCloseFile(FILE *f) : file(f) {}
~AutoCloseFile() {
release();
}
~AutoCloseFile() { release(); }

AutoCloseFile(const AutoCloseFile &) = default;
AutoCloseFile(AutoCloseFile &&) = delete;
Expand All @@ -65,7 +64,7 @@ static std::string strip_prefix(std::string_view resolved_path,
return std::string(resolved_path);
}

const auto& base = *path_prefix;
const auto &base = *path_prefix;
if (!resolved_path.starts_with(base)) {
return std::string(resolved_path);
}
Expand All @@ -75,14 +74,12 @@ static std::string strip_prefix(std::string_view resolved_path,

struct stat s;


static std::string resolve_extension(std::string resolved_path) {
if (stat(resolved_path.c_str(), &s) == 0) {
return resolved_path;
}

if (resolved_path.size() >= 3 &&
resolved_path.compare(resolved_path.size() - 3, 3, ".js") == 0) {
if (resolved_path.size() >= 3 && resolved_path.compare(resolved_path.size() - 3, 3, ".js") == 0) {
return resolved_path;
}

Expand Down Expand Up @@ -159,7 +156,7 @@ static std::string resolve_path(std::string_view path, std::string_view base) {
return resolve_extension(std::move(resolved_path));
}

static JSObject* get_module(JSContext* cx, JS::SourceText<mozilla::Utf8Unit> &source,
static JSObject *get_module(JSContext *cx, JS::SourceText<mozilla::Utf8Unit> &source,
std::string_view resolved_path, const JS::CompileOptions &opts) {
RootedObject module(cx, JS::CompileModule(cx, opts, source));
if (!module) {
Expand Down Expand Up @@ -216,7 +213,7 @@ static JSObject *get_module(JSContext *cx, std::string_view specifier,
return get_module(cx, source, resolved_path, opts);
}

static JSObject* get_builtin_module(JSContext* cx, HandleValue id, HandleObject builtin) {
static JSObject *get_builtin_module(JSContext *cx, HandleValue id, HandleObject builtin) {
RootedValue module_val(cx);
MOZ_ASSERT(id.isString());
if (!JS::MapGet(cx, moduleRegistry, id, &module_val)) {
Expand All @@ -238,7 +235,7 @@ static JSObject* get_builtin_module(JSContext* cx, HandleValue id, HandleObject
bool firstValue = true;
for (size_t i = 0; i < length; ++i) {
if (firstValue) {
firstValue = false;
firstValue = false;
} else {
code += ", ";
}
Expand All @@ -262,14 +259,14 @@ static JSObject* get_builtin_module(JSContext* cx, HandleValue id, HandleObject
firstValue = true;
for (size_t i = 0; i < length; ++i) {
if (firstValue) {
firstValue = false;
firstValue = false;
} else {
code += ", ";
}

code += "e";
code += std::to_string(i);

code += " as '";
const auto &prop = props[i];
JS::RootedValue key(cx, js::IdToValue(prop));
Expand Down Expand Up @@ -310,36 +307,52 @@ static JSObject* get_builtin_module(JSContext* cx, HandleValue id, HandleObject
return module;
}

JSObject* module_resolve_hook(JSContext* cx, HandleValue referencingPrivate,
HandleObject moduleRequest) {
RootedString specifier(cx, GetModuleRequestSpecifier(cx, moduleRequest));
bool module_load_hook(JSContext *cx, JS::HandleScript referrer, JS::HandleObject module_reques,
JS::HandleValue hostDefined, JS::HandleValue payload, uint32_t lineNumber,
JS::ColumnNumberOneOrigin columnNumber) {
RootedString specifier(cx, GetModuleRequestSpecifier(cx, module_reques));
if (!specifier) {
return nullptr;
return false;
}

RootedValue path_val(cx, StringValue(specifier));
auto path = JS_EncodeStringToUTF8(cx, specifier);
if (!path) {
return nullptr;
return false;
}

RootedValue builtin_val(cx);
if (!MapGet(cx, builtinModules, path_val, &builtin_val)) {
return nullptr;
return false;
}
if (!builtin_val.isUndefined()) {
RootedValue specifier_val(cx, StringValue(specifier));
RootedObject builtin_obj(cx, &builtin_val.toObject());
return get_builtin_module(cx, specifier_val, builtin_obj);
RootedObject result(cx, get_builtin_module(cx, specifier_val, builtin_obj));
if (!result) {
return false;
}
return FinishLoadingImportedModule(cx, referrer, module_reques, payload, result, false);
}

RootedValue ref_priv(cx);
if (referrer) {
ref_priv = JS::GetScriptPrivate(referrer);
}

RootedObject info(cx, &referencingPrivate.toObject());
if (ref_priv.isUndefined() || !ref_priv.isObject()) {
JS_ReportErrorASCII(cx, "Module referrer has no private value");
return false;
}

RootedObject info(cx, &ref_priv.toObject());
RootedValue parent_path_val(cx);
if (!JS_GetProperty(cx, info, "id", &parent_path_val)) {
return nullptr;
return false;
}
if (!parent_path_val.isString()) {
return nullptr;
JS_ReportErrorASCII(cx, "Module referrer has no id property");
return false;
}

HostString str = core::encode(cx, parent_path_val);
Expand All @@ -348,11 +361,15 @@ JSObject* module_resolve_hook(JSContext* cx, HandleValue referencingPrivate,
JS::CompileOptions opts(cx, *COMPILE_OPTS);
auto stripped = strip_prefix(resolved_path, PATH_PREFIX);
opts.setFileAndLine(stripped.c_str(), 1);
return get_module(cx, path.get(), resolved_path, opts);
RootedObject result(cx, get_module(cx, path.get(), resolved_path, opts));
if (!result) {
return false;
}
return FinishLoadingImportedModule(cx, referrer, module_reques, payload, result, false);
}

bool module_metadata_hook(JSContext* cx, HandleValue referencingPrivate, HandleObject metaObject) {
RootedObject info(cx, &referencingPrivate.toObject());
bool module_metadata_hook(JSContext *cx, HandleValue ref_priv, HandleObject meta_obj) {
RootedObject info(cx, &ref_priv.toObject());
RootedValue parent_id_val(cx);
if (!JS_GetProperty(cx, info, "id", &parent_id_val)) {
return false;
Expand All @@ -367,29 +384,29 @@ bool module_metadata_hook(JSContext* cx, HandleValue referencingPrivate, HandleO
if (builtin_val.isUndefined()) {
return false;
}
JS_SetProperty(cx, metaObject, "builtin", builtin_val);
JS_SetProperty(cx, meta_obj, "builtin", builtin_val);
return true;
}

ScriptLoader::ScriptLoader(api::Engine* engine, JS::CompileOptions *opts,
ScriptLoader::ScriptLoader(api::Engine *engine, JS::CompileOptions *opts,
mozilla::Maybe<std::string> path_prefix) {
MOZ_ASSERT(!SCRIPT_LOADER);
ENGINE = engine;
SCRIPT_LOADER = this;
COMPILE_OPTS = opts;
PATH_PREFIX = std::move(path_prefix);
JSContext* cx = engine->cx();
JSContext *cx = engine->cx();
moduleRegistry.init(cx, JS::NewMapObject(cx));
builtinModules.init(cx, JS::NewMapObject(cx));
MOZ_RELEASE_ASSERT(moduleRegistry);
MOZ_RELEASE_ASSERT(builtinModules);
JSRuntime *rt = JS_GetRuntime(cx);
SetModuleResolveHook(rt, module_resolve_hook);
SetModuleLoadHook(rt, module_load_hook);
SetModuleMetadataHook(rt, module_metadata_hook);
}

bool ScriptLoader::define_builtin_module(const char* id, HandleValue builtin) {
JSContext* cx = ENGINE->cx();
bool ScriptLoader::define_builtin_module(const char *id, HandleValue builtin) {
JSContext *cx = ENGINE->cx();
RootedString id_str(cx, JS_NewStringCopyZ(cx, id));
if (!id_str) {
return false;
Expand All @@ -409,9 +426,7 @@ bool ScriptLoader::define_builtin_module(const char* id, HandleValue builtin) {
return true;
}

void ScriptLoader::enable_module_mode(bool enable) {
MODULE_MODE = enable;
}
void ScriptLoader::enable_module_mode(bool enable) { MODULE_MODE = enable; }

bool ScriptLoader::load_resolved_script(JSContext *cx, std::string_view specifier_sv,
std::string_view resolved_path_sv,
Expand All @@ -424,30 +439,30 @@ bool ScriptLoader::load_resolved_script(JSContext *cx, std::string_view specifie

FILE *file = fopen(resolved_path, "r");
if (!file) {
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError,
specifier, resolved_path, std::strerror(errno));
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError, specifier, resolved_path,
std::strerror(errno));
}

AutoCloseFile autoclose(file);
if (fseek(file, 0, SEEK_END) != 0) {
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError,
specifier, resolved_path, "can't read from file");
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError, specifier, resolved_path,
"can't read from file");
}
size_t len = ftell(file);
if (fseek(file, 0, SEEK_SET) != 0) {
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError,
specifier, resolved_path, "can't read from file");
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError, specifier, resolved_path,
"can't read from file");
}

UniqueChars buf(js_pod_malloc<char>(len + 1));
if (!buf) {
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError,
specifier, resolved_path, "out of memory while reading file");
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError, specifier, resolved_path,
"out of memory while reading file");
}
size_t cc = fread(buf.get(), sizeof(char), len, file);
if (cc != len) {
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError,
specifier, resolved_path, "error reading file");
return api::throw_error(cx, ScriptLoaderErrors::ModuleLoadingError, specifier, resolved_path,
"error reading file");
}

return script.init(cx, std::move(buf), len);
Expand All @@ -471,8 +486,10 @@ bool ScriptLoader::load_script(JSContext *cx, std::string_view path,
return load_resolved_script(cx, path, resolved, script);
}

bool ScriptLoader::eval_top_level_script(std::string_view path, JS::SourceText<mozilla::Utf8Unit> &source,
MutableHandleValue result, MutableHandleValue tla_promise) {
bool ScriptLoader::eval_top_level_script(std::string_view path,
JS::SourceText<mozilla::Utf8Unit> &source,
MutableHandleValue result,
MutableHandleValue tla_promise) {
JSContext *cx = ENGINE->cx();

JS::CompileOptions opts(cx, *COMPILE_OPTS);
Expand All @@ -491,7 +508,20 @@ bool ScriptLoader::eval_top_level_script(std::string_view path, JS::SourceText<m
if (!module) {
return false;
}
if (!ModuleLink(cx, module)) {
RootedValue hostDefined(cx, ObjectValue(*module));
if (!LoadRequestedModules(
cx, module, hostDefined,
[](JSContext *cx, JS::Handle<JS::Value> hd) {
JS::RootedObject mod(cx, &hd.toObject());
return JS::ModuleLink(cx, mod);
},
[](JSContext *cx, JS::Handle<JS::Value>, JS::Handle<JS::Value> error) {
JS_SetPendingException(cx, error);
return true;
})) {
return false;
}
if (JS_IsExceptionPending(cx)) {
return false;
}
} else {
Expand Down