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(importStar): Cache non‑module results #80

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
21 changes: 14 additions & 7 deletions tslib.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,20 @@ var __setModuleDefault = Object.create ? (function(o, v) {
o["default"] = v;
};

export function __importStar(mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
export var __importStar = function (mod) {
var cache = typeof WeakMap === "function" ? new WeakMap() : null;
Copy link
Member

Choose a reason for hiding this comment

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

Are you proposing this be implemented in TypeScript as well for inline helper emit? If so we'd need to introduce a checker error if you declare your own value named WeakMap at the top of a module.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue there is that this is supposed to be an optimisation when two different modules that use tslib import the same CommonJS module, the value returned by __importStar is the same value for both imports, e.g.:

// modA.js
Object.defineProperty(exports, "__esModule", { value: true });
var tslib = require("tslib");

exports.example = tslib.__importStar(require("example"));
// modB.js
Object.defineProperty(exports, "__esModule", { value: true });
var tslib = require("tslib");

exports.example = tslib.__importStar(require("example"));
// test.js
var assert = require("assert");

var modA = require("./modA.js");
var modB = require("./modA.js");

// The following passes regardless of whether `example` has `__esModule` or not:
assert.strictEqual(modA.example, modB.example);

It doesn’t make sense to include the module cache in inline helpers, as modA and modB would then each have their own cache, and every new local __imporStar call would then have a cache miss, since the cache wouldn’t be global.

__importStar = function (mod) {
if (mod === null || (typeof mod !== "object" && typeof mod !== "function")) return { default: mod };
Copy link
Member

Choose a reason for hiding this comment

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

nit: Parens aren't needed here, since && has higher precedence than ||.

Suggested change
if (mod === null || (typeof mod !== "object" && typeof mod !== "function")) return { default: mod };
if (mod === null || typeof mod !== "object" && typeof mod !== "function") return { default: mod };

if (mod.__esModule) return mod;
if (cache && cache.has(mod)) return cache.get(mod);
var result = {};
for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
if (cache) cache.set(mod, result);
return result;
}
return __importStar(mod);
};

export function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
Expand Down
17 changes: 12 additions & 5 deletions tslib.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,18 @@ var __createBinding;
};

__importStar = function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
var cache = typeof WeakMap === "function" ? new WeakMap() : null;
__importStar = function (mod) {
if (mod === null || (typeof mod !== "object" && typeof mod !== "function")) return { default: mod };
Copy link
Member

Choose a reason for hiding this comment

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

nit: Parens aren't necessary here.

Suggested change
if (mod === null || (typeof mod !== "object" && typeof mod !== "function")) return { default: mod };
if (mod === null || typeof mod !== "object" && typeof mod !== "function") return { default: mod };

if (mod.__esModule) return mod;
if (cache && cache.has(mod)) return cache.get(mod);
var result = {};
for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
if (cache) cache.set(mod, result);
return result;
}
return __importStar(mod);
};

__importDefault = function (mod) {
Expand Down