Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ dist/

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

deps/artifacts/
deps/aws-lambda-cpp*/
deps/curl*/
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions test/handlers/extensionless/esm-extensionless
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

// This should fail because it's ESM syntax in a CJS context
export const handler = async (event) => {
return "This should fail";
};
8 changes: 8 additions & 0 deletions test/handlers/extensionless/index
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';
// This is a CommonJS module without file extension

module.exports.handler = async (event) => {
return "Hello from extensionless CJS";
};
9 changes: 9 additions & 0 deletions test/handlers/pkg-less/cjsAndMjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

import { someESMFunction } from './esmModule.js'; // ESM import

module.exports.handler = async (event) => { // CJS export
return someESMFunction(event);
};

export const esm = 'This is ESM syntax'; // ESM export
9 changes: 9 additions & 0 deletions test/handlers/pkg-less/cjsImportCjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

const { getMessage } = require('./cjsModule.cjs')

exports.handler = async (_event) => {
return getMessage();
}
10 changes: 10 additions & 0 deletions test/handlers/pkg-less/cjsImportESM.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

// This static import is not allowed in CJS
import { getMessage } from './esmModule';

module.exports.handler = async () => {
return getMessage();
};
8 changes: 8 additions & 0 deletions test/handlers/pkg-less/cjsInMjs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

// This should fail because it's CJS syntax in a ESM context
module.exports.handler = async (_event) => {
return 'This should fail';
};
7 changes: 7 additions & 0 deletions test/handlers/pkg-less/cjsModule.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

module.exports.getMessage = () => {
return "Hello from CJS!";
};
7 changes: 7 additions & 0 deletions test/handlers/pkg-less/esmImportCjs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

import { getMessage } from './cjsModule.cjs';

export const handler = async (_event) => {
return getMessage();
};
6 changes: 6 additions & 0 deletions test/handlers/pkg-less/esmInCjs.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

// This should fail because it's ESM syntax in a CJS context
export const handler = async (_event) => {
return 'This should fail';
};
9 changes: 9 additions & 0 deletions test/handlers/pkg-less/esmModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

export const handler = async (_event) => {
return 'Hello from ESM.js';
};

export const getMessage = () => {
return "Hello from ESM!";
};
7 changes: 7 additions & 0 deletions test/handlers/pkg-less/esmRequireCjs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

const { getMessage } = require('./cjsModule.cjs')

export const handler = async (_event) => {
return getMessage();
};
8 changes: 8 additions & 0 deletions test/handlers/pkg/type-cjs/cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';
// This is a CommonJS module without file extension

module.exports.handler = async (event) => {
return "Hello from extensionless CJS";
};
7 changes: 7 additions & 0 deletions test/handlers/pkg/type-cjs/cjsModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

module.exports.handler = async (_event) => {
return 'Hello from CJS.js';
};
6 changes: 6 additions & 0 deletions test/handlers/pkg/type-cjs/esm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

// This should fail because it's ESM syntax in a CJS context
export const handler = async (event) => {
return "This should fail";
};
6 changes: 6 additions & 0 deletions test/handlers/pkg/type-cjs/esmModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

// This should fail because it's ESM syntax in a CJS context
export const handler = async (_event) => {
return 'This should fail';
};
3 changes: 3 additions & 0 deletions test/handlers/pkg/type-cjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
8 changes: 8 additions & 0 deletions test/handlers/pkg/type-esm/cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';
// This is a CommonJS module without file extension

module.exports.handler = async (event) => {
return "Hello from extensionless CJS";
};
8 changes: 8 additions & 0 deletions test/handlers/pkg/type-esm/cjsModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

'use strict';

// This should fail because it's CJS syntax in a ESM context
module.exports.handler = async (_event) => {
return 'This should fail';
};
6 changes: 6 additions & 0 deletions test/handlers/pkg/type-esm/esm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

// This should fail because it's ESM syntax in a CJS context
export const handler = async (event) => {
return "This should fail";
};
5 changes: 5 additions & 0 deletions test/handlers/pkg/type-esm/esmModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */

export const handler = async (_event) => {
return 'Hello from ESM.js';
};
3 changes: 3 additions & 0 deletions test/handlers/pkg/type-esm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
161 changes: 161 additions & 0 deletions test/unit/UserFunctionTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
HandlerNotFound,
ImportModuleError,
MalformedHandlerName,
UserCodeSyntaxError,
} = require('lambda-runtime/Errors.js');
const UserFunction = require('lambda-runtime/UserFunction.js');

Expand Down Expand Up @@ -250,6 +251,166 @@ describe('UserFunction.load method', () => {

response.should.be.resolvedWith('moon');
});

it('should successfully load a CJS handler from extensionless file (no package.json)', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'extensionless'),
'index.handler',
);
const response = await handler('test event');

response.should.equal('Hello from extensionless CJS');
});

it('should fail to load ESM syntax from extensionless file (no package.json)', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'extensionless'),
'esm-extensionless.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should load CJS handler from extensionless file with type:commonjs', async () => {
// package.json is ignored in the case of extensionless
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-cjs'),
'cjs.handler',
);
const response = await handler('test event');

response.should.equal('Hello from extensionless CJS');
});

it('should fail to load ESM handler from extensionless file with type:commonjs', async () => {
// package.json is ignored in the case of extensionless
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-cjs'),
'esm.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should load CJS handler from extensionless file with type:module', async () => {
// package.json is ignored in the case of extensionless
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-esm'),
'cjs.handler',
);
const response = await handler('test event');

response.should.equal('Hello from extensionless CJS');
});

it('should fail to load ESM handler from extensionless file with type:module', async () => {
// package.json is ignored in the case of extensionless
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-esm'),
'esm.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should load CJS handler from JS file with type:commonjs', async () => {
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-cjs'),
'cjsModule.handler',
);
const response = await handler('test event');

response.should.equal('Hello from CJS.js');
});

it('should fail to load ESM handler from JS file with type:commonjs', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-cjs'),
'esmModule.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should load ESM handler from JS file with type:module', async () => {
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-esm'),
'esmModule.handler',
);
const response = await handler('test event');

response.should.equal('Hello from ESM.js');
});

it('should fail to load CJS handler from JS file with type:module', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg', 'type-esm'),
'cjsModule.handler',
).should.be.rejectedWith(
ReferenceError,
/module is not defined in ES module scope/,
);
});

it('should fail to load ESM handler from JS file without type context', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'esmModule.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should fail to load CJS handler from MJS file without type context', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'cjsInMjs.handler',
).should.be.rejectedWith(
ReferenceError,
/module is not defined in ES module scope/,
);
});

it('should fail to load ESM handler from CJS file without type context', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'esmInCjs.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should fail to load mixed context handler from JS file without type context', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'cjsAndMjs.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should successfully load ESM handler importing from CJS', async () => {
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'esmImportCjs.handler',
);

const response = await handler();
response.should.equal('Hello from CJS!');
});

it('should fail when CJS tries to import from ESM using static import', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'cjsImportESM.handler',
).should.be.rejectedWith(UserCodeSyntaxError);
});

it('should successfully load CJS handler importing from CJS', async () => {
const handler = await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'cjsImportCjs.handler',
);

const response = await handler();
response.should.equal('Hello from CJS!');
});

it('should fail when using require in .mjs', async () => {
await UserFunction.load(
path.join(HANDLERS_ROOT, 'pkg-less'),
'esmRequireCjs.handler',
).should.be.rejectedWith(
ReferenceError,
/require is not defined in ES module scope/,
);
});
});

describe('type guards HandlerFunction', () => {
Expand Down