/* * Copyright (c) 2025, Shannon Booth * Copyright (c) 2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #include #include namespace Web::HTML { // https://html.spec.whatwg.org/multipage/webappapis.html#extract-error ErrorInformation extract_error_information(JS::VM& vm, JS::Value exception) { // 1. Let attributes be an empty map keyed by IDL attributes. ErrorInformation attributes; // 2. Set attributes[error] to exception. attributes.error = exception; // 3. Set attributes[message], attributes[filename], attributes[lineno], and attributes[colno] to // implementation-defined values derived from exception. attributes.message = [&] { if (auto object = exception.as_if()) { if (MUST(object->has_own_property(vm.names.message))) { auto message = object->get_without_side_effects(vm.names.message); return message.to_string_without_side_effects(); } } return MUST(String::formatted("Uncaught exception: {}", exception)); }(); // FIXME: This offset is relative to the javascript source. Other browsers appear to do it relative // to the entire source document! Calculate that somehow. // NB: If we got an Error object, then try and extract the information from the location the object was made. if (auto object = exception.as_if(); object && object->error_data()) { for (auto const& frame : object->error_data()->traceback()) { auto source_range = frame.source_range(); if (source_range.start.line != 0 || source_range.start.column != 0) { attributes.filename = MUST(String::from_byte_string(source_range.filename())); attributes.lineno = source_range.start.line; attributes.colno = source_range.start.column; break; } } } // NB: Otherwise, we fall back to try and find the location of the invocation of the function itself. else { for (auto const& frame : vm.stack_trace()) { if (frame.source_range.has_value()) { auto const& source_range = *frame.source_range; attributes.filename = MUST(String::from_byte_string(source_range.filename())); attributes.lineno = source_range.start.line; attributes.colno = source_range.start.column; break; } } } // 4. Return attributes. return attributes; } }