Skip to content

Commit c5432bf

Browse files
committed
fix: use fallback if no generateMarkup
1 parent 1a8673c commit c5432bf

File tree

3 files changed

+18
-42
lines changed

3 files changed

+18
-42
lines changed

packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
export const expectedFailures = new Set([
1111
'attribute-global-html/as-component-prop/undeclared/index.js',
1212
'attribute-global-html/as-component-prop/without-@api/index.js',
13-
'exports/component-as-default/index.js',
1413
'known-boolean-attributes/default-def-html-attributes/static-on-component/index.js',
1514
'render-dynamic-value/index.js',
1615
'slot-forwarding/slots/mixed/index.js',

packages/@lwc/ssr-compiler/src/compile-js/index.ts

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ import { catalogWireAdapters } from './wire';
2020

2121
import { removeDecoratorImport } from './remove-decorator-import';
2222
import { generateError } from './errors';
23-
import type { NodePath } from 'estree-toolkit';
2423
import type { ComponentTransformOptions } from '../shared';
2524
import type {
2625
Identifier as EsIdentifier,
2726
Program as EsProgram,
2827
Decorator as EsDecorator,
29-
ClassDeclaration as EsClassDeclaration,
3028
} from 'estree';
3129
import type { Visitors, ComponentMetaState } from './types';
3230
import type { CompilationMode } from '@lwc/shared';
@@ -74,7 +72,15 @@ const visitors: Visitors = {
7472
},
7573
ClassDeclaration(path, state) {
7674
const { node } = path;
77-
if (123) {
75+
if (
76+
node?.superClass &&
77+
// export default class extends LightningElement {}
78+
(is.exportDefaultDeclaration(path.parentPath) ||
79+
// class Cmp extends LightningElement {}; export default Cmp
80+
path.scope
81+
?.getBinding(node.id.name)
82+
?.references.some((ref) => is.exportDefaultDeclaration(ref.parent)))
83+
) {
7884
// If it's a default-exported class with a superclass, then it's an LWC component!
7985
state.isLWC = true;
8086
if (node.id) {
@@ -212,43 +218,6 @@ const visitors: Visitors = {
212218
},
213219
};
214220

215-
/**
216-
* Determines whether a class declaration is an LWC component. Returns true if the class has a
217-
* superclass and is a default export.
218-
*/
219-
function isLwcComponent(path: NodePath<EsClassDeclaration>) {
220-
const { node } = path;
221-
if (!node?.superClass) {
222-
// class Cmp {}
223-
return false;
224-
}
225-
if (is.exportDefaultDeclaration(path.parentPath)) {
226-
// export default class Cmp extends LightningElement {} => true
227-
return true;
228-
}
229-
const binding = path.scope?.getBinding(node.id.name);
230-
if (!binding) {
231-
// Never exported
232-
return false;
233-
}
234-
return binding.references.some((ref) => {
235-
const { parent } = ref;
236-
if (is.exportDefaultDeclaration(parent)) {
237-
// class Cmp extends LightningElement {}; export default Cmp
238-
return true;
239-
}
240-
if (is.exportSpecifier(parent)) {
241-
// class Cmp extends LightningElement {}; export { Cmp as default }
242-
// class Cmp extends LightningElement {}; export { Cmp as 'default' }
243-
const exported = is.identifier(parent.exported)
244-
? parent.exported.name
245-
: parent.exported.value;
246-
return exported === 'default';
247-
}
248-
return false;
249-
});
250-
}
251-
252221
function validateUniqueDecorator(decorators: EsDecorator[]) {
253222
if (decorators.length < 2) {
254223
return;

packages/@lwc/ssr-runtime/src/render.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ type GenerateMarkupFnVariants =
174174
| GenerateMarkupFnAsyncNoGen
175175
| GenerateMarkupFnSyncNoGen;
176176

177-
interface ComponentWithGenerateMarkup {
177+
interface ComponentWithGenerateMarkup extends LightningElementConstructor {
178178
[SYMBOL__GENERATE_MARKUP]: GenerateMarkupFnVariants;
179179
}
180180

@@ -195,6 +195,14 @@ export async function serverSideRenderComponent(
195195
markup += segment;
196196
};
197197

198+
if (!generateMarkup) {
199+
// If a non-component is accidentally provided, render an empty template
200+
emit(`<${tagName}>`);
201+
fallbackTmplNoYield(emit, null, null, null, Component, null);
202+
emit(`</${tagName}>`);
203+
return markup;
204+
}
205+
198206
if (mode === 'asyncYield') {
199207
for await (const segment of (generateMarkup as GenerateMarkupFn)(
200208
tagName,

0 commit comments

Comments
 (0)