Repository: localstack/localstack

Issue:
bug: Lambda won't execute if using ES6 export syntax
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

When running a lambda using E6S export syntax:

```
export const handler = (event) => {
  console.log("hello world");
  console.log(event);

  return event;
};
```

with `"type": "module"` set in my `package.json` I get the following error:

```
ERROR   Uncaught Exception      {"errorType":"Error","errorMessage":"Must use import to load ES Module: /var/task/index.js\nrequire() of ES modules is not supported.\nrequire() of /var/task/index.js from /var/runtime/UserFunction.js is an ES module file as it is a .js file whose nearest parent package.json contains \"type\": \"module\" which defines all .js files in that package scope as ES modules.\nInstead rename index.js to end in .cjs, change the requiring code to use import(), or remove \"type\": \"module\" from /var/task/package.json.\n","code":"ERR_REQUIRE_ESM","stack":["Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /var/task/index.js","require() of ES modules is not supported.","require() of /var/task/index.js from /var/runtime/UserFunction.js is an ES module file as it is a .js file whose nearest parent package.json contains \"type\": \"module\" which defines all .js files in that package scope as ES modules.","Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove \"type\": \"module\" from /var/task/package.json.","","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1080:13)","    at Module.load (internal/modules/cjs/loader.js:928:32)","    at Function.Module._load (internal/modules/cjs/loader.js:769:14)","    at Module.require (internal/modules/cjs/loader.js:952:19)","    at require (internal/modules/cjs/helpers.js:88:18)","    at _tryRequire (/var/runtime/UserFunction.js:75:12)","    at _loadUserApp (/var/runtime/UserFunction.js:95:12)","    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)","    at Object.<anonymous> (/var/runtime/index.js:43:30)","    at Module._compile (internal/modules/cjs/loader.js:1063:30)"]}
```

I have provisioned the lambda with terraform:

```
resource "aws_lambda_function" "test" {
  filename         = "lambda.zip"
  function_name    = "test-function"
  role             = aws_iam_role.lambda.arn
  handler          = "index.handler"
  source_code_hash = data.archive_file.lambda_my_function.output_base64sha256

  runtime = "nodejs14.x"
}
```

### Expected Behavior

I'd expect the lambda to execute successfully without any errors.

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

docker compose up with example docker-compose.yaml file:

```
version: "3.8"

services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack
    network_mode: bridge
    ports:
      - "127.0.0.1:53:53"                # only required for Pro (DNS)
      - "127.0.0.1:53:53/udp"            # only required for Pro (DNS)
      - "127.0.0.1:443:443"              # only required for Pro (LocalStack HTTPS Edge Proxy)
      - "127.0.0.1:4510-4559:4510-4559"  # external service port range
      - "127.0.0.1:4566:4566"            # LocalStack Edge Proxy
    environment:
      - DEBUG=${DEBUG-}
      - DATA_DIR=${DATA_DIR-}
      - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}
      - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-}  # only required for Pro
      - HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "${TMPDIR:-/tmp}/localstack:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"
```

Infrastructure is provisioned with the terraform in the example above. The code runs fine when using CommonJS.


Lambda is triggered with the following command:

```
awslocal lambda invoke --function-name test-function --invocation-type Event --cli-binary-format raw-in-base64-out --payload '{ "key": "value" }' output.txt
```

### Environment

```markdown
- OS: macOS Mojave 10.14.6 (18G9216)
- LocalStack: latest
```


### Anything else?

_No response_


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [developer guide](https://docs.localstack.cloud/developer-guide/).
Waiting for the fix as well.

Resolving patch:
diff --git a/localstack/contrib/thundra.py b/localstack/contrib/thundra.py
--- a/localstack/contrib/thundra.py
+++ b/localstack/contrib/thundra.py
@@ -20,6 +20,7 @@
     LAMBDA_RUNTIME_NODEJS10X,
     LAMBDA_RUNTIME_NODEJS12X,
     LAMBDA_RUNTIME_NODEJS14X,
+    LAMBDA_RUNTIME_NODEJS16X,
     LAMBDA_RUNTIME_PYTHON36,
     LAMBDA_RUNTIME_PYTHON37,
     LAMBDA_RUNTIME_PYTHON38,
@@ -251,6 +252,7 @@ def _is_node_lambda_with_support_version(func_details):
         LAMBDA_RUNTIME_NODEJS10X,
         LAMBDA_RUNTIME_NODEJS12X,
         LAMBDA_RUNTIME_NODEJS14X,
+        LAMBDA_RUNTIME_NODEJS16X,
     ]
 
 
diff --git a/localstack/services/awslambda/lambda_executors.py b/localstack/services/awslambda/lambda_executors.py
--- a/localstack/services/awslambda/lambda_executors.py
+++ b/localstack/services/awslambda/lambda_executors.py
@@ -1596,11 +1596,8 @@ def docker_image_for_lambda(cls, lambda_function: LambdaFunction):
             )
         docker_tag = runtime
         docker_image = config.LAMBDA_CONTAINER_REGISTRY
-        if runtime == "nodejs14.x" and docker_image == DEFAULT_LAMBDA_CONTAINER_REGISTRY:
-            # TODO temporary fix until lambci image for nodejs14.x becomes available
-            docker_image = "localstack/lambda-js"
-        elif (
-            runtime in ["python3.9", "dotnet6"]
+        if (
+            runtime in ["nodejs14.x", "nodejs16.x", "python3.9", "dotnet6"]
             and docker_image == DEFAULT_LAMBDA_CONTAINER_REGISTRY
         ):
             # TODO temporary fix until we support AWS images via https://github.com/localstack/localstack/pull/4734
diff --git a/localstack/services/awslambda/lambda_utils.py b/localstack/services/awslambda/lambda_utils.py
--- a/localstack/services/awslambda/lambda_utils.py
+++ b/localstack/services/awslambda/lambda_utils.py
@@ -35,6 +35,7 @@
 LAMBDA_RUNTIME_NODEJS10X = "nodejs10.x"
 LAMBDA_RUNTIME_NODEJS12X = "nodejs12.x"
 LAMBDA_RUNTIME_NODEJS14X = "nodejs14.x"
+LAMBDA_RUNTIME_NODEJS16X = "nodejs16.x"
 LAMBDA_RUNTIME_JAVA8 = "java8"
 LAMBDA_RUNTIME_JAVA8_AL2 = "java8.al2"
 LAMBDA_RUNTIME_JAVA11 = "java11"


Test patch:
diff --git a/tests/integration/awslambda/test_lambda.py b/tests/integration/awslambda/test_lambda.py
--- a/tests/integration/awslambda/test_lambda.py
+++ b/tests/integration/awslambda/test_lambda.py
@@ -28,6 +28,7 @@
     LAMBDA_RUNTIME_JAVA11,
     LAMBDA_RUNTIME_NODEJS12X,
     LAMBDA_RUNTIME_NODEJS14X,
+    LAMBDA_RUNTIME_NODEJS16X,
     LAMBDA_RUNTIME_PROVIDED,
     LAMBDA_RUNTIME_PROVIDED_AL2,
     LAMBDA_RUNTIME_PYTHON36,
@@ -129,15 +130,12 @@
         LAMBDA_RUNTIME_PYTHON39,
     ]
     if use_docker()
-    else [LAMBDA_RUNTIME_PYTHON38]
+    else [LAMBDA_RUNTIME_PYTHON39]
 )
 NODE_TEST_RUNTIMES = (
-    [
-        LAMBDA_RUNTIME_NODEJS12X,
-        LAMBDA_RUNTIME_NODEJS14X,
-    ]
+    [LAMBDA_RUNTIME_NODEJS12X, LAMBDA_RUNTIME_NODEJS14X, LAMBDA_RUNTIME_NODEJS16X]
     if use_docker()
-    else [LAMBDA_RUNTIME_NODEJS14X]
+    else [LAMBDA_RUNTIME_NODEJS16X]
 )
 JAVA_TEST_RUNTIMES = (
     [
diff --git a/tests/integration/awslambda/test_lambda.snapshot.json b/tests/integration/awslambda/test_lambda.snapshot.json
--- a/tests/integration/awslambda/test_lambda.snapshot.json
+++ b/tests/integration/awslambda/test_lambda.snapshot.json
@@ -2098,7 +2098,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_nodejs_lambda_with_context[nodejs12.x]": {
-    "recorded-date": "31-05-2022, 10:55:32",
+    "recorded-date": "29-06-2022, 14:08:17",
     "recorded-content": {
       "creation": {
         "CreateFunctionResponse": {
@@ -2116,7 +2116,7 @@
           "Timeout": 30,
           "MemorySize": 128,
           "LastModified": "date",
-          "CodeSha256": "MlXLROhdNy8i69HOUf0wqrfTKXYXQIc3HMhQG4F9LB0=",
+          "CodeSha256": "3jEBtyb2KUD3L+wjo2wrrPA4jZOoF8ChFMUusDWbLj4=",
           "Version": "$LATEST",
           "Environment": {
             "Variables": {}
@@ -2175,7 +2175,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_nodejs_lambda_with_context[nodejs14.x]": {
-    "recorded-date": "31-05-2022, 10:55:51",
+    "recorded-date": "29-06-2022, 14:08:42",
     "recorded-content": {
       "creation": {
         "CreateFunctionResponse": {
@@ -2193,7 +2193,7 @@
           "Timeout": 30,
           "MemorySize": 128,
           "LastModified": "date",
-          "CodeSha256": "cZw+JxADt8hFp5xIcU4Jrxu2TZWQnVu+y8fv8Qf0puk=",
+          "CodeSha256": "ZbP5K8v1m1DKY3iDo8k4EpoPFvvKHGQ4g1eAqQB7DhA=",
           "Version": "$LATEST",
           "Environment": {
             "Variables": {}
@@ -2252,7 +2252,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda[nodejs12.x]": {
-    "recorded-date": "31-05-2022, 08:57:11",
+    "recorded-date": "29-06-2022, 14:09:31",
     "recorded-content": {
       "creation-result": {
         "CreateFunctionResponse": {
@@ -2270,7 +2270,7 @@
           "Timeout": 30,
           "MemorySize": 128,
           "LastModified": "date",
-          "CodeSha256": "1ZWDqdmf1MvbQMl5CfNdVoSC/Z7F44gLXk1YdagaRNM=",
+          "CodeSha256": "TDaIWH66B82q4TnqnIhZgD2x+p+96nI6rSE9HXXiznA=",
           "Version": "$LATEST",
           "Environment": {
             "Variables": {}
@@ -2307,7 +2307,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda[nodejs14.x]": {
-    "recorded-date": "31-05-2022, 08:57:39",
+    "recorded-date": "29-06-2022, 14:09:54",
     "recorded-content": {
       "creation-result": {
         "CreateFunctionResponse": {
@@ -2325,7 +2325,7 @@
           "Timeout": 30,
           "MemorySize": 128,
           "LastModified": "date",
-          "CodeSha256": "7y+zJoq0DaqK7hNkDTjOOPhKEZoXp9BzRVHKCkjly9g=",
+          "CodeSha256": "FyZTLMLZ1/YzuefMVDmlaCkIs4Xn7+Tl06v/Odn2r1k=",
           "Version": "$LATEST",
           "Environment": {
             "Variables": {}
@@ -2362,7 +2362,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda_with_payload_containing_quotes[nodejs12.x]": {
-    "recorded-date": "31-05-2022, 08:58:01",
+    "recorded-date": "29-06-2022, 14:10:44",
     "recorded-content": {
       "invoke-result": {
         "ResponseMetadata": {
@@ -2379,7 +2379,7 @@
     }
   },
   "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda_with_payload_containing_quotes[nodejs14.x]": {
-    "recorded-date": "31-05-2022, 08:58:26",
+    "recorded-date": "29-06-2022, 14:14:00",
     "recorded-content": {
       "invoke-result": {
         "ResponseMetadata": {
@@ -3510,5 +3510,154 @@
         "Payload": "null"
       }
     }
+  },
+  "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_nodejs_lambda_with_context[nodejs16.x]": {
+    "recorded-date": "29-06-2022, 14:09:04",
+    "recorded-content": {
+      "creation": {
+        "CreateFunctionResponse": {
+          "ResponseMetadata": {
+            "HTTPStatusCode": 201,
+            "HTTPHeaders": {}
+          },
+          "FunctionName": "<function-name:1>",
+          "FunctionArn": "arn:aws:lambda:<region>:111111111111:function:<function-name:1>",
+          "Runtime": "nodejs16.x",
+          "Role": "arn:aws:iam::111111111111:role/<resource:1>",
+          "Handler": "lambda_integration.handler",
+          "CodeSize": 357,
+          "Description": "",
+          "Timeout": 30,
+          "MemorySize": 128,
+          "LastModified": "date",
+          "CodeSha256": "uVmr6ovSYJO64EQiS8S650A9oJx3GoftkAKnMc+qyC4=",
+          "Version": "$LATEST",
+          "Environment": {
+            "Variables": {}
+          },
+          "TracingConfig": {
+            "Mode": "PassThrough"
+          },
+          "RevisionId": "<uuid:1>",
+          "State": "Pending",
+          "StateReason": "The function is being created.",
+          "StateReasonCode": "Creating",
+          "PackageType": "Zip",
+          "Architectures": [
+            "x86_64"
+          ],
+          "EphemeralStorage": {
+            "Size": 512
+          }
+        },
+        "CreateEventSourceMappingResponse": null
+      },
+      "invocation": {
+        "ResponseMetadata": {
+          "HTTPStatusCode": 200,
+          "HTTPHeaders": {}
+        },
+        "StatusCode": 200,
+        "ExecutedVersion": "$LATEST",
+        "Payload": {
+          "context": {
+            "callbackWaitsForEmptyEventLoop": true,
+            "functionVersion": "$LATEST",
+            "functionName": "<function-name:1>",
+            "memoryLimitInMB": "128",
+            "logGroupName": "/aws/lambda/<function-name:1>",
+            "logStreamName": "<log-stream-name:1>",
+            "clientContext": {
+              "custom": {
+                "foo": "bar"
+              },
+              "client": {
+                "snap": [
+                  "crackle",
+                  "pop"
+                ]
+              },
+              "env": {
+                "fizz": "buzz"
+              }
+            },
+            "invokedFunctionArn": "arn:aws:lambda:<region>:111111111111:function:<function-name:1>",
+            "awsRequestId": "<uuid:2>"
+          }
+        }
+      }
+    }
+  },
+  "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda[nodejs16.x]": {
+    "recorded-date": "29-06-2022, 14:10:21",
+    "recorded-content": {
+      "creation-result": {
+        "CreateFunctionResponse": {
+          "ResponseMetadata": {
+            "HTTPStatusCode": 201,
+            "HTTPHeaders": {}
+          },
+          "FunctionName": "<function-name:1>",
+          "FunctionArn": "arn:aws:lambda:<region>:111111111111:function:<function-name:1>",
+          "Runtime": "nodejs16.x",
+          "Role": "arn:aws:iam::111111111111:role/<resource:1>",
+          "Handler": "lambda_handler.handler",
+          "CodeSize": 335,
+          "Description": "",
+          "Timeout": 30,
+          "MemorySize": 128,
+          "LastModified": "date",
+          "CodeSha256": "3GBnArrUtgFhMTBMZtWWWJEU/GuwTKpe9DUTIhzEUjI=",
+          "Version": "$LATEST",
+          "Environment": {
+            "Variables": {}
+          },
+          "TracingConfig": {
+            "Mode": "PassThrough"
+          },
+          "RevisionId": "<uuid:1>",
+          "State": "Pending",
+          "StateReason": "The function is being created.",
+          "StateReasonCode": "Creating",
+          "PackageType": "Zip",
+          "Architectures": [
+            "x86_64"
+          ],
+          "EphemeralStorage": {
+            "Size": 512
+          }
+        },
+        "CreateEventSourceMappingResponse": null
+      },
+      "invocation-result": {
+        "ResponseMetadata": {
+          "HTTPStatusCode": 200,
+          "HTTPHeaders": {}
+        },
+        "StatusCode": 200,
+        "ExecutedVersion": "$LATEST",
+        "Payload": {
+          "statusCode": 200,
+          "body": "\"response from localstack lambda: {\\\"event_type\\\":\\\"test_lambda\\\"}\""
+        }
+      }
+    }
+  },
+  "tests/integration/awslambda/test_lambda.py::TestNodeJSRuntimes::test_invoke_nodejs_lambda_with_payload_containing_quotes[nodejs16.x]": {
+    "recorded-date": "29-06-2022, 14:12:09",
+    "recorded-content": {
+      "invoke-result": {
+        "ResponseMetadata": {
+          "HTTPStatusCode": 200,
+          "HTTPHeaders": {}
+        },
+        "StatusCode": 200,
+        "ExecutedVersion": "$LATEST",
+        "Payload": {
+          "statusCode": 200,
+          "body": "\"response from localstack lambda: {\\\"test_var\\\":\\\"test_string' with some quotes\\\"}\""
+        }
+      }
+    }
   }
 }