playwright 1.47.0 → 1.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,7 +29,7 @@ async function resolve(specifier, context, defaultResolve) {
29
29
  var _currentFileDepsColle;
30
30
  if (context.parentURL && context.parentURL.startsWith('file://')) {
31
31
  const filename = _url.default.fileURLToPath(context.parentURL);
32
- const resolved = (0, _transform.resolveHook)(filename, specifier, true);
32
+ const resolved = (0, _transform.resolveHook)(filename, specifier);
33
33
  if (resolved !== undefined) specifier = _url.default.pathToFileURL(resolved).toString();
34
34
  }
35
35
  const result = await defaultResolve(specifier, context, defaultResolve);
@@ -88,16 +88,15 @@ function loadAndValidateTsconfigsForFile(file) {
88
88
  }
89
89
  const pathSeparator = process.platform === 'win32' ? ';' : ':';
90
90
  const builtins = new Set(_module.default.builtinModules);
91
- function resolveHook(filename, specifier, isESM) {
91
+ function resolveHook(filename, specifier) {
92
92
  if (specifier.startsWith('node:') || builtins.has(specifier)) return;
93
93
  if (!shouldTransform(filename)) return;
94
- if (isRelativeSpecifier(specifier)) return (0, _util.resolveImportSpecifierExtension)(_path.default.resolve(_path.default.dirname(filename), specifier), false, isESM);
94
+ if (isRelativeSpecifier(specifier)) return (0, _util.resolveImportSpecifierAfterMapping)(_path.default.resolve(_path.default.dirname(filename), specifier), false);
95
95
 
96
96
  /**
97
- * TypeScript discourages path-mapping into node_modules
98
- * (https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages).
99
- * It seems like TypeScript tries path-mapping first, but does not look at the `package.json` or `index.js` files in ESM.
100
- * If path-mapping doesn't yield a result, TypeScript falls back to the default resolution (typically node_modules).
97
+ * TypeScript discourages path-mapping into node_modules:
98
+ * https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages
99
+ * However, if path-mapping doesn't yield a result, TypeScript falls back to the default resolution through node_modules.
101
100
  */
102
101
  const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
103
102
  const tsconfigs = loadAndValidateTsconfigsForFile(filename);
@@ -133,7 +132,7 @@ function resolveHook(filename, specifier, isESM) {
133
132
  let candidate = value;
134
133
  if (value.includes('*')) candidate = candidate.replace('*', matchedPartOfSpecifier);
135
134
  candidate = _path.default.resolve(tsconfig.pathsBase, candidate);
136
- const existing = (0, _util.resolveImportSpecifierExtension)(candidate, true, isESM);
135
+ const existing = (0, _util.resolveImportSpecifierAfterMapping)(candidate, true);
137
136
  if (existing) {
138
137
  longestPrefixLength = keyPrefix.length;
139
138
  pathMatchedByLongestPrefix = existing;
@@ -145,7 +144,7 @@ function resolveHook(filename, specifier, isESM) {
145
144
  if (_path.default.isAbsolute(specifier)) {
146
145
  // Handle absolute file paths like `import '/path/to/file'`
147
146
  // Do not handle module imports like `import 'fs'`
148
- return (0, _util.resolveImportSpecifierExtension)(specifier, false, isESM);
147
+ return (0, _util.resolveImportSpecifierAfterMapping)(specifier, false);
149
148
  }
150
149
  }
151
150
  function shouldTransform(filename) {
@@ -218,7 +217,7 @@ function installTransformIfNeeded() {
218
217
  const originalResolveFilename = _module.default._resolveFilename;
219
218
  function resolveFilename(specifier, parent, ...rest) {
220
219
  if (parent) {
221
- const resolved = resolveHook(parent.filename, specifier, false);
220
+ const resolved = resolveHook(parent.filename, specifier);
222
221
  if (resolved !== undefined) specifier = resolved;
223
222
  }
224
223
  return originalResolveFilename.call(this, specifier, parent, ...rest);
package/lib/util.js CHANGED
@@ -23,7 +23,7 @@ exports.getPackageJsonPath = getPackageJsonPath;
23
23
  exports.mergeObjects = mergeObjects;
24
24
  exports.normalizeAndSaveAttachment = normalizeAndSaveAttachment;
25
25
  exports.relativeFilePath = relativeFilePath;
26
- exports.resolveImportSpecifierExtension = resolveImportSpecifierExtension;
26
+ exports.resolveImportSpecifierAfterMapping = resolveImportSpecifierAfterMapping;
27
27
  exports.resolveReporterOutputPath = resolveReporterOutputPath;
28
28
  exports.sanitizeFilePathBeforeExtension = sanitizeFilePathBeforeExtension;
29
29
  exports.serializeError = serializeError;
@@ -277,11 +277,23 @@ function folderIsModule(folder) {
277
277
  // Rely on `require` internal caching logic.
278
278
  return require(packageJsonPath).type === 'module';
279
279
  }
280
+ const packageJsonMainFieldCache = new Map();
281
+ function getMainFieldFromPackageJson(packageJsonPath) {
282
+ if (!packageJsonMainFieldCache.has(packageJsonPath)) {
283
+ let mainField;
284
+ try {
285
+ mainField = JSON.parse(_fs.default.readFileSync(packageJsonPath, 'utf8')).main;
286
+ } catch {}
287
+ packageJsonMainFieldCache.set(packageJsonPath, mainField);
288
+ }
289
+ return packageJsonMainFieldCache.get(packageJsonPath);
290
+ }
280
291
 
281
- // This follows the --moduleResolution=bundler strategy from tsc.
282
- // https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#moduleresolution-bundler
292
+ // This method performs "file extension subsitution" to find the ts, js or similar source file
293
+ // based on the import specifier, which might or might not have an extension. See TypeScript docs:
294
+ // https://www.typescriptlang.org/docs/handbook/modules/reference.html#file-extension-substitution.
283
295
  const kExtLookups = new Map([['.js', ['.jsx', '.ts', '.tsx']], ['.jsx', ['.tsx']], ['.cjs', ['.cts']], ['.mjs', ['.mts']], ['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']]]);
284
- function resolveImportSpecifierExtension(resolved, isPathMapping, isESM) {
296
+ function resolveImportSpecifierExtension(resolved) {
285
297
  if (fileExists(resolved)) return resolved;
286
298
  for (const [ext, others] of kExtLookups) {
287
299
  if (!resolved.endsWith(ext)) continue;
@@ -291,23 +303,43 @@ function resolveImportSpecifierExtension(resolved, isPathMapping, isESM) {
291
303
  }
292
304
  break; // Do not try '' when a more specific extension like '.jsx' matched.
293
305
  }
306
+ }
294
307
 
295
- // After TypeScript path mapping, here's how directories with a `package.json` are resolved:
296
- // - `package.json#exports` is not respected
297
- // - `package.json#main` is respected only in CJS mode
298
- // - `index.js` default is respected only in CJS mode
299
- //
300
- // More info:
301
- // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages
302
- // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution
303
- // - https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules
308
+ // This method resolves directory imports and performs "file extension subsitution".
309
+ // It is intended to be called after the path mapping resolution.
310
+ //
311
+ // Directory imports follow the --moduleResolution=bundler strategy from tsc.
312
+ // https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution
313
+ // https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler
314
+ //
315
+ // See also Node.js "folder as module" behavior:
316
+ // https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules.
317
+ function resolveImportSpecifierAfterMapping(resolved, afterPathMapping) {
318
+ const resolvedFile = resolveImportSpecifierExtension(resolved);
319
+ if (resolvedFile) return resolvedFile;
320
+ if (dirExists(resolved)) {
321
+ const packageJsonPath = _path.default.join(resolved, 'package.json');
322
+ if (afterPathMapping) {
323
+ // Most notably, the module resolution algorithm is not performed after the path mapping.
324
+ // This means no node_modules lookup or package.json#exports.
325
+ //
326
+ // Only the "folder as module" Node.js behavior is respected:
327
+ // - consult `package.json#main`;
328
+ // - look for `index.js` or similar.
329
+ const mainField = getMainFieldFromPackageJson(packageJsonPath);
330
+ const mainFieldResolved = mainField ? resolveImportSpecifierExtension(_path.default.resolve(resolved, mainField)) : undefined;
331
+ return mainFieldResolved || resolveImportSpecifierExtension(_path.default.join(resolved, 'index'));
332
+ }
304
333
 
305
- const shouldNotResolveDirectory = isPathMapping && isESM;
306
- if (!shouldNotResolveDirectory && dirExists(resolved)) {
307
334
  // If we import a package, let Node.js figure out the correct import based on package.json.
308
- if (fileExists(_path.default.join(resolved, 'package.json'))) return resolved;
335
+ // This also covers the "main" field for "folder as module".
336
+ if (fileExists(packageJsonPath)) return resolved;
337
+
338
+ // Implement the "folder as module" Node.js behavior.
339
+ // Note that we do not delegate to Node.js, because we support this for ESM as well,
340
+ // following the TypeScript "bundler" mode.
309
341
  const dirImport = _path.default.join(resolved, 'index');
310
- return resolveImportSpecifierExtension(dirImport, isPathMapping, isESM);
342
+ return resolveImportSpecifierExtension(dirImport);
311
343
  }
312
344
  }
313
345
  function fileExists(resolved) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.47.0",
3
+ "version": "1.47.1",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "license": "Apache-2.0",
60
60
  "dependencies": {
61
- "playwright-core": "1.47.0"
61
+ "playwright-core": "1.47.1"
62
62
  },
63
63
  "optionalDependencies": {
64
64
  "fsevents": "2.3.2"