pulumi/tests/integration/dynamic/nodejs-reserved-identifier-...
Will Jones 0a6876c527
Support serialising reserved NodeJS identifiers (#15879)
This commit addresses part of #11942, in which we fail to serialise
closures whose code would use reserved identifiers like `exports`. This
is due to a change we made where module imports are hoisted to avoid
importing the same module multiple times. Previously, code adopted a
strategy of passing all dependencies using a `with` statement, viz.:

```typescript
function x() {
  return (function () {
    with({ fooBarBaz: require("foo/bar/baz"), ... }) {
      // Use of fooBarBaz
    }
  }).apply(...)
}

function y() {
  return (function () {
    with({ fooBarBaz: require("foo/bar/baz"), ... }) {
      // Use of fooBarBaz
    }
  }).apply(...)
}
```

This was changed to remove the duplicate imports, yielding code like:

```typescript
const fooBarBaz = require("foo/bar/baz")

function x() {
  return (function () {
    with({ ... }) {
      // Use of fooBarBaz
    }
  }).apply(...)
}

function y() {
  return (function () {
    with({ ... }) {
      // Use of fooBarBaz
    }
  }).apply(...)
}
```

However, while the previous approach would work with reserved
identifiers such as `exports` (`with({ exports, ... }) { ... }` is
perfectly acceptable), the new one does not (`const exports = ...` is
not acceptable since NodeJS will not allow redeclaration of the
`exports` global).

This commit combines the two approaches. Modules are only imported once,
but if an import would use a reserved identifier, we generate a fresh
non-conflicting identifier and alias this using a `with` statement. For
example:

```typescript
const fooBarBaz = require("foo/bar/baz")

// __pulumi_closure_import_exports is generated to avoid shadowing the reserved "exports"
const __pulumi_closure_import_exports = require("some/other/module")

function x() {
  return (function () {
    with({ exports: __pulumi_closure_import_exports, ... }) {
      // Use of fooBarBaz and exports
    }
  }).apply(...)
}
```

Note that it is not expected that #11942 will be solved in its entirety.
While this commit fixes code that introduces identifiers like `exports`,
the introduction in question in that issue is caused by the use of
`pulumi.output(...)` in the constructor of a dynamic resource provider.
Since dynamic resource providers are implemented under the hood by
serialising their code, we attempt to serialise `pulumi.output` and its
dependency chain. This commit allows us to make more progress in that
regard, but other things go wrong thereafter. Fixing the deeper issue
that underpins #11942 (and likely other challenges with dynamic
providers) is probably a more involved piece of work.
2024-04-10 15:12:43 +00:00
..
Pulumi.yaml Support serialising reserved NodeJS identifiers (#15879) 2024-04-10 15:12:43 +00:00
index.ts Support serialising reserved NodeJS identifiers (#15879) 2024-04-10 15:12:43 +00:00
package.json Support serialising reserved NodeJS identifiers (#15879) 2024-04-10 15:12:43 +00:00