Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(labs/ssr): Prevent exposure of window object on globalThis #3431

Merged
merged 7 commits into from
Dec 13, 2022
Merged
5 changes: 5 additions & 0 deletions .changeset/loud-radios-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lit-labs/ssr': major
---

dom shim does not expose the window object
steveworkman marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 0 additions & 5 deletions packages/labs/ssr/src/lib/dom-shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ export const getWindow = ({
...props,
};

window.window = window;

if (includeJSBuiltIns) {
Object.assign(window, {
// No-op any async tasks
Expand Down Expand Up @@ -204,8 +202,5 @@ export const installWindowOnGlobal = (props: {[key: string]: unknown} = {}) => {
const window = getWindow({props});
// Copy initial window globals to node global
Object.assign(globalThis, window);
// Set up global reference to window so all globals added to window are
// added to the node global
globalThis.window = globalThis as typeof globalThis & Window;
}
};
4 changes: 3 additions & 1 deletion packages/labs/ssr/src/test/integration/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ export const ssrMiddleware = () => {
module = await import(`../tests/${testFile}-ssr.js`);
} else {
// mode === 'vm'
const window = getWindow({includeJSBuiltIns: true});
window.window = window;
steveworkman marked this conversation as resolved.
Show resolved Hide resolved
const loader = new ModuleLoader({
global: getWindow({includeJSBuiltIns: true}),
global: window,
});
module = (
await loader.importModule(
Expand Down
57 changes: 35 additions & 22 deletions packages/labs/ssr/src/test/lib/dom-shim_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,44 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

import {getWindow} from '../../lib/dom-shim.js';
import {installWindowOnGlobal, getWindow} from '../../lib/dom-shim.js';
import {test} from 'uvu';
// eslint-disable-next-line import/extensions
import * as assert from 'uvu/assert';

const window = getWindow({}) as unknown as Window;
const {HTMLElement} = window.window;
function testWithHtmlElement(HTMLElement: any) {
test('elements without an attached shadow root should expose a null value from the "shadowRoot" property', () => {
class UnattachedShadowRoot extends HTMLElement {}
const element = new UnattachedShadowRoot();
assert.is(element.shadowRoot, null);
});
test('elements defined with an open shadow root should expose it\'s shadow root from the "shadowRoot" property', () => {
class OpenShadowRoot extends HTMLElement {}
const element = new OpenShadowRoot();
const shadow = element.attachShadow({mode: 'open'});
assert.is(shadow, element.shadowRoot);
assert.is(shadow.host, element);
});
test('elements defined with a closed shadow root should expose a null value from the "shadowRoot" property', () => {
class ClosedShadowRoot extends HTMLElement {}
const element = new ClosedShadowRoot();
element.attachShadow({mode: 'closed'});
assert.is(element.shadowRoot, null);
});

test('elements without an attached shadow root should expose a null value from the "shadowRoot" property', () => {
class UnattachedShadowRoot extends HTMLElement {}
const element = new UnattachedShadowRoot();
assert.is(element.shadowRoot, null);
});
test('elements defined with an open shadow root should expose it\'s shadow root from the "shadowRoot" property', () => {
class OpenShadowRoot extends HTMLElement {}
const element = new OpenShadowRoot();
const shadow = element.attachShadow({mode: 'open'});
assert.is(shadow, element.shadowRoot);
assert.is(shadow.host, element);
});
test('elements defined with a closed shadow root should expose a null value from the "shadowRoot" property', () => {
class ClosedShadowRoot extends HTMLElement {}
const element = new ClosedShadowRoot();
element.attachShadow({mode: 'closed'});
assert.is(element.shadowRoot, null);
});
test.run();
}

test.run();
function testWithGlobalShim() {
installWindowOnGlobal({});
const {HTMLElement} = globalThis;
testWithHtmlElement(HTMLElement);
}
function testWithWindow() {
const window = getWindow({});
const {HTMLElement} = window;
testWithHtmlElement(HTMLElement);
}

testWithWindow();
testWithGlobalShim();
10 changes: 6 additions & 4 deletions packages/labs/ssr/src/test/lib/render-lit_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import {RenderInfo} from '../../index.js';

import type * as testModule from '../test-files/render-test-module.js';

const window = getWindow({
includeJSBuiltIns: true,
props: {require: createRequire(import.meta.url)},
});
window.window = window;
steveworkman marked this conversation as resolved.
Show resolved Hide resolved
const loader = new ModuleLoader({
global: getWindow({
includeJSBuiltIns: true,
props: {require: createRequire(import.meta.url)},
}),
global: window,
});

/**
Expand Down