Repository: servo/servo
File: components/script/module_loading.rs (Rust)

Code before:

        // c. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] + requestedModulesCount.
        let pending_modules_count = state.pending_modules_count.get();
        state
            .pending_modules_count
            .set(pending_modules_count + requested_modules_count);

        // d. For each ModuleRequest Record request of module.[[RequestedModules]], do
        for index in 0..requested_modules_count {
            // i. If AllImportAttributesSupported(request.[[Attributes]]) is false, then
            // Note: Gecko will call hasFirstUnsupportedAttributeKey on each module request,
            // GetRequestedModuleSpecifier will do it for us.
            let jsstr = unsafe { GetRequestedModuleSpecifier(*cx, module_handle, index) };

            if jsstr.is_null() {
                // 1. Let error be ThrowCompletion(a newly created SyntaxError object).
                let error = RethrowError::from_pending_exception(cx);

                state.load_state.as_ref().inspect(|load_state| {
                    load_state
                        .error_to_rethrow
                        .borrow_mut()
                        .get_or_insert(error.clone());
                });

                // 2. Perform ContinueModuleLoading(state, error).
                continue_module_loading(global, state, Err(error));
            } else {
                let specifier =
                    unsafe { jsstr_to_string(*cx, std::ptr::NonNull::new(jsstr).unwrap()) };

                // ii. Else if module.[[LoadedModules]] contains a LoadedModuleRequest Record record
                // such that ModuleRequestsEqual(record, request) is true, then
                let loaded_module = module.find_descendant_inside_module_map(global, &specifier);

                match loaded_module {
                    // 1. Perform InnerModuleLoading(state, record.[[Module]]).
                    Some(module) => inner_module_loading(global, state, module),
                    // iii. Else,
                    None => {
                        rooted!(in(*cx) let mut referrer = UndefinedValue());
                        unsafe { JS_GetModulePrivate(module_handle.get(), referrer.handle_mut()) };

                        // 1. Perform HostLoadImportedModule(module, request, state.[[HostDefined]], state).
                        host_load_imported_module(
                            cx,
                            Some(module.clone()),
                            referrer.handle().into_handle(),
                            specifier,
                            state.load_state.clone(),
                            Payload::GraphRecord(state.clone()),

Review comment (bug):
Is this a spec oversight? At this point we don't have a `[[ErrorToRethrow]]` and inside `rejected_steps` `on_complete` will receive null, so the error will be ignored and treated as a network failure, making `invalid-import-errors-order.html` and `unsupported-attribute.html` fail.

Code after:

        // c. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] + requestedModulesCount.
        let pending_modules_count = state.pending_modules_count.get();
        state
            .pending_modules_count
            .set(pending_modules_count + requested_modules_count);

        // d. For each ModuleRequest Record request of module.[[RequestedModules]], do
        for index in 0..requested_modules_count {
            // i. If AllImportAttributesSupported(request.[[Attributes]]) is false, then
            // Note: Gecko will call hasFirstUnsupportedAttributeKey on each module request,
            // GetRequestedModuleSpecifier will do it for us.
            let jsstr = unsafe { GetRequestedModuleSpecifier(*cx, module_handle, index) };

            if jsstr.is_null() {
                // 1. Let error be ThrowCompletion(a newly created SyntaxError object).
                let error = RethrowError::from_pending_exception(cx);

                // See Step 7. of `host_load_imported_module`.
                state.load_state.as_ref().inspect(|load_state| {
                    load_state
                        .error_to_rethrow
                        .borrow_mut()
                        .get_or_insert(error.clone());
                });

                // 2. Perform ContinueModuleLoading(state, error).
                continue_module_loading(global, state, Err(error));
            } else {
                let specifier =
                    unsafe { jsstr_to_string(*cx, std::ptr::NonNull::new(jsstr).unwrap()) };

                // ii. Else if module.[[LoadedModules]] contains a LoadedModuleRequest Record record
                // such that ModuleRequestsEqual(record, request) is true, then
                let loaded_module = module.find_descendant_inside_module_map(global, &specifier);

                match loaded_module {
                    // 1. Perform InnerModuleLoading(state, record.[[Module]]).
                    Some(module) => inner_module_loading(global, state, module),
                    // iii. Else,
                    None => {
                        rooted!(in(*cx) let mut referrer = UndefinedValue());
                        unsafe { JS_GetModulePrivate(module_handle.get(), referrer.handle_mut()) };

                        // 1. Perform HostLoadImportedModule(module, request, state.[[HostDefined]], state).
                        host_load_imported_module(
                            cx,
                            Some(module.clone()),
                            referrer.handle().into_handle(),
                            specifier,
                            state.load_state.clone(),