Skip to content
Merged
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
46 changes: 44 additions & 2 deletions builtins/web/worker-location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,35 @@ namespace builtins::web::worker_location {

JS::PersistentRooted<JSObject *> WorkerLocation::url;

namespace {
DEF_ERR(LocationNotSetError, JSEXN_TYPEERR, "{0} can only be used during request handling, "
"or if an initialization-time location was set "
"using `--init-location`", 1)
bool ensure_location_access(JSContext *cx, const char *name) {
auto *engine = api::Engine::get(cx);

if (engine->state() == api::EngineState::Initialized) {
return true;
}

if (engine->state() == api::EngineState::ScriptPreInitializing && WorkerLocation::url.get()) {
return true;
}

return api::throw_error(cx, LocationNotSetError, name);
}
} // namespace

#define WorkerLocation_ACCESSOR_GET(field) \
bool field##_get(JSContext *cx, unsigned argc, JS::Value *vp) { \
auto result = WorkerLocation::MethodHeaderWithName(0, cx, argc, vp, __func__); \
if (result.isErr()) { \
return false; \
} \
auto [args, self] = result.unwrap(); \
REQUEST_HANDLER_ONLY("location." #field) \
if (!ensure_location_access(cx, "location." #field)) { \
return false; \
} \
return url::URL::field(cx, WorkerLocation::url, args.rval()); \
}

Expand Down Expand Up @@ -80,7 +101,28 @@ bool WorkerLocation::init_class(JSContext *cx, JS::HandleObject global) {
}

bool install(api::Engine *engine) {
return WorkerLocation::init_class(engine->cx(), engine->global());
if (!WorkerLocation::init_class(engine->cx(), engine->global())) {
return false;
}

const auto &init_location = engine->init_location();
if (init_location) {
// Set the URL for `globalThis.location` to the configured value.
JSContext *cx = engine->cx();
JS::RootedObject url_instance(
cx, JS_NewObjectWithGivenProto(cx, &url::URL::class_, url::URL::proto_obj));
if (!url_instance) {
return false;
}

auto *uri_bytes = new uint8_t[init_location->size() + 1];
std::copy(init_location->begin(), init_location->end(), uri_bytes);
jsurl::SpecString spec(uri_bytes, init_location->size(), init_location->size());

WorkerLocation::url = url::URL::create(cx, url_instance, spec);
}

return true;
}

} // namespace builtins::web::worker_location
Expand Down
5 changes: 5 additions & 0 deletions componentize.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ usage() {
echo " Specifying '--strip-path-prefix' will cause the provided prefix to be stripped from paths in stack traces and the debugger"
echo " Specifying '--legacy-script' causes evaluation as a legacy JS script instead of a module"
echo " Specifying '--wpt-mode' enables WPT compatibility mode"
echo " Specifying '--init-location url' allows setting the URL to use for 'globalThis.location' during initialization"
exit 1
}

Expand Down Expand Up @@ -55,6 +56,10 @@ do
STARLING_ARGS="$STARLING_ARGS $1 $2"
shift 2
;;
--init-location)
STARLING_ARGS="$STARLING_ARGS $1 $2"
shift 2
;;
-v|--verbose)
STARLING_ARGS="$1 $STARLING_ARGS"
VERBOSE=1
Expand Down
5 changes: 5 additions & 0 deletions include/config-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class ConfigParser {
}
} else if (args[i] == "--wpt-mode") {
config_->wpt_mode = true;
} else if (args[i] == "--init-location") {
if (i + 1 < args.size()) {
config_->init_location = mozilla::Some(args[i + 1]);
i++;
}
} else if (args[i].starts_with("--")) {
std::cerr << "Unknown option: " << args[i] << std::endl;
exit(1);
Expand Down
2 changes: 2 additions & 0 deletions include/extension-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct EngineConfig {
mozilla::Maybe<std::string> content_script_path = mozilla::Nothing();
mozilla::Maybe<std::string> content_script = mozilla::Nothing();
mozilla::Maybe<std::string> path_prefix = mozilla::Nothing();
mozilla::Maybe<std::string> init_location = mozilla::Nothing();
bool module_mode = true;

/**
Expand Down Expand Up @@ -84,6 +85,7 @@ class Engine {
EngineState state();
bool debugging_enabled();
bool wpt_mode();
const mozilla::Maybe<std::string> &init_location() const;

void finish_pre_initialization();

Expand Down
3 changes: 3 additions & 0 deletions runtime/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ bool Engine::debugging_enabled() {
return config_->debugging;
}
bool Engine::wpt_mode() { return config_->wpt_mode; }
const mozilla::Maybe<std::string> &Engine::init_location() const {
return config_->init_location;
}

void Engine::finish_pre_initialization() {
MOZ_ASSERT(state_ == EngineState::ScriptPreInitializing);
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/init-location/expect_serve_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
stdout [0] :: Log: localhost
2 changes: 2 additions & 0 deletions tests/e2e/init-location/expect_wizer_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Componentizing e2e/init-location/init-location.js into e2e/init-location/init-location.wasm
Log: http://foo.bar/
6 changes: 6 additions & 0 deletions tests/e2e/init-location/init-location.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
console.log(self.location.href);

addEventListener("fetch", (event) => {
console.log(self.location.hostname);
event.respondWith(new Response("ok"));
});
1 change: 1 addition & 0 deletions tests/e2e/init-location/runtime-args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--init-location http://foo.bar/
Empty file.
2 changes: 2 additions & 0 deletions tests/e2e/no-init-location/expect_wizer_stderr.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Exception while evaluating top-level script
e2e/no-init-location/no-init-location.js:1:9 TypeError: location.href can only be used during request handling, or if an initialization-time location was set using `--init-location`
1 change: 1 addition & 0 deletions tests/e2e/no-init-location/no-init-location.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(self.location);
11 changes: 10 additions & 1 deletion tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test_component="${3:-}"
test_name="$(basename $test_dir)"
test_serve_path="${4:-}"
componentize_flags="${COMPONENTIZE_FLAGS:-}"
runtime_args_file="$test_dir/runtime-args"

wasmtime="${WASMTIME:-wasmtime}"

Expand Down Expand Up @@ -42,6 +43,10 @@ if [ -z "$test_component" ]; then

runtime_args="--strip-path-prefix $test_top_level $runtime_args"

if [ -f "$runtime_args_file" ]; then
runtime_args="$runtime_args $(cat $runtime_args_file)"
fi

# Run Wizer
set +e
PREOPEN_DIR="$test_top_level" "$test_runtime/componentize.sh" $componentize_flags $runtime_args "$test_component" 1> "$stdout_log" 2> "$stderr_log"
Expand All @@ -64,6 +69,10 @@ if [ -z "$test_component" ]; then
fi

if [ -f "$test_wizer_stdout_expectation" ]; then
# Strip $test_top_level from stdout and stderr logs if present
mv "$stdout_log" "$stdout_log.orig"
cat "$stdout_log.orig" | sed "s|$test_top_level||g" > "$stdout_log"
rm "$stdout_log.orig"
cmp -b "$stdout_log" "$test_wizer_stdout_expectation"
fi

Expand All @@ -86,7 +95,7 @@ if [ -z "$test_component" ]; then
rm "$test_component"
fi
exit 0
fi
fi
fi
fi

Expand Down
2 changes: 2 additions & 0 deletions tests/tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ test_e2e(stream-forwarding)
test_e2e(multi-stream-forwarding)
test_e2e(teed-stream-as-outgoing-body)
test_e2e(init-script)
test_e2e(no-init-location)
test_e2e(init-location)

integration_tests(
blob
Expand Down