Repository navigation
Description
Component
Link (also affects AnchorButton through the shared BaseAnchor implementation)
Package version
3.1.3 in the tested repository source checkout. Published affected-version range has not been determined.
@microsoft/fast-element version
3.0.0
Environment
macOS
Chromium 141.0.7390.37
Firefox 142.0.1
WebKit 26.0Current Behavior
With target="_blank" rel="noopener noreferrer", regular click/Enter produces a destination with window.opener === null and an empty document.referrer. Modified activation of the same component instead produces a non-null opener and a non-empty referrer.
Independently, referrerpolicy="no-referrer" is honored by regular activation but ignored by modified activation. Both fluent-link and fluent-anchor-button behave this way. A native <a> with the same attributes does not show this discrepancy.
Relevant code path: BaseAnchor.handleNavigation. Both components inherit it:
private handleNavigation(newTab: boolean): void {
newTab ? window.open(this.href, '_blank') : this.internalProxyAnchor.click();
}Regular activation clicks the proxy anchor, which has the configured attributes. Modified activation uses a separate navigation path that does not carry those attributes.
Expected Behavior
Modified pointer and keyboard activation should preserve applicable rel and referrerpolicy settings while opening the requested new browsing context:
rel="noopener noreferrer":window.opener === nullanddocument.referrer === "".referrerpolicy="no-referrer":document.referrer === "", independently ofrel.
Reproduction
The following self-contained command bundles the real, unmodified component source in memory and serves a local comparison page plus a diagnostic destination. It creates no files. Run it from the repository root after the normal dependency installation, open the printed URL, and use Ctrl+C to stop it.
NX_TASK_TARGET_PROJECT=fluentui-repo NX_DAEMON=false yarn nx exec -- node --input-type=module <<'NODE'
import { createServer } from 'node:http';
import { build } from 'esbuild';
const { outputFiles } = await build({
stdin: {
contents: [
"import './packages/web-components/src/link/define.ts';",
"import './packages/web-components/src/anchor-button/define.ts';",
].join('\n'),
resolveDir: process.cwd(),
sourcefile: 'activation-repro.ts',
loader: 'ts',
},
bundle: true,
write: false,
format: 'esm',
platform: 'browser',
target: 'es2022',
tsconfigRaw: { compilerOptions: {
experimentalDecorators: true,
useDefineForClassFields: false,
} },
});
const html = '<!doctype html><title>Link activation comparison</title>' +
'<script type="module" src="/bundle.js"></script>' +
'<p><fluent-link id="link-rel" href="/result" target="_blank" rel="noopener noreferrer">Link: rel</fluent-link></p>' +
'<p><fluent-anchor-button id="button-rel" href="/result" target="_blank" rel="noopener noreferrer">AnchorButton: rel</fluent-anchor-button></p>' +
'<p><fluent-link id="link-policy" href="/result" target="_blank" referrerpolicy="no-referrer">Link: referrerpolicy</fluent-link></p>' +
'<p><fluent-anchor-button id="button-policy" href="/result" target="_blank" referrerpolicy="no-referrer">AnchorButton: referrerpolicy</fluent-anchor-button></p>' +
'<p><a id="native" href="/result" target="_blank" rel="noopener noreferrer">Native anchor control</a></p>';
const destination = '<!doctype html><title>Activation result</title><pre id="result"></pre>' +
'<script>window.activationResult = {' +
'openerIsNull: window.opener === null, referrer: document.referrer };' +
'document.querySelector("#result").textContent = JSON.stringify(window.activationResult, null, 2);</script>';
const server = createServer((request, response) => {
const path = new URL(request.url, 'http://127.0.0.1').pathname;
response.setHeader('Content-Type', path === '/bundle.js' ? 'text/javascript' : 'text/html');
response.end(path === '/bundle.js' ? outputFiles[0].text : path === '/result' ? destination : html);
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
console.log('Open http://127.0.0.1:' + server.address().port + '/');
NODESteps to reproduce
- Run the command above and open the printed local URL.
- Regular-click Link: rel. The new tab prints
openerIsNull: trueandreferrer: "". Close that tab. - Cmd+click the same link on macOS, or Ctrl+click on Windows/Linux. The new tab prints
openerIsNull: falseand a non-empty referrer instead. - Focus the same link and press Ctrl+Enter; also check Cmd+Enter on macOS. Observe the same discrepancy.
- Repeat with AnchorButton: rel; the result is identical.
- Compare regular and modified activation of both referrerpolicy examples. The regular path prints an empty referrer; the modified path prints a non-empty referrer.
- Repeat regular and modified clicks on Native anchor control. Both produce
openerIsNull: trueand an empty referrer.
On macOS, real Ctrl+click is a context-menu gesture, so use Cmd+click for the mouse comparison. The destination only displays its own navigation metadata; it does not modify another page.
Regression coverage: Add real-popup checks to the existing AnchorButton and Link Playwright specs for regular click/Enter and platform-appropriate modified click/Enter. Assert the opener and referrer values, test referrerpolicy separately from rel, retain a native-anchor control, and verify navigation still reaches the requested URL. Exercise Chromium, Firefox, and WebKit.
Are you reporting an Accessibility issue?
no
Suggested severity
Medium - Has workaround
Products/sites affected
No specific consuming product identified.
Are you willing to submit a PR to fix?
Owner to be assigned from @microsoft/fui-wc.
Validations
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- The provided reproduction is a minimal reproducible example of the bug.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
[-]Web Components: maintenance follow-up[/-][+][Bug]: Web Components maintenance follow-up[/+][-][Bug]: Web Components maintenance follow-up[/-][+][Bug]: Modified link activation does not preserve navigation attributes[/+][-][Bug]: Modified link activation does not preserve navigation attributes[/-][+][Bug]: Link and AnchorButton ignore rel/referrerpolicy during modified activation[/+]