Skip to content
This repository was archived by the owner on Apr 16, 2020. It is now read-only.

Commit 10290e9

Browse files
committed
esm: implement exports main
1 parent 6d3fa24 commit 10290e9

File tree

4 files changed

+37
-34
lines changed

4 files changed

+37
-34
lines changed

lib/internal/modules/esm/default_resolve.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ const legacyExtensionFormatMap = {
2525
'__proto__': null,
2626
'.cjs': 'cjs',
2727
'.js': 'cjs',
28-
'.json': 'cjs',
29-
'.mjs': 'esm',
30-
'.node': 'cjs'
28+
'.mjs': 'esm'
3129
};
3230

3331
function resolve(specifier, parentURL) {

src/env.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,16 @@ struct PackageConfig {
8282
struct HasMain {
8383
enum Bool { No, Yes };
8484
};
85+
struct HasExports {
86+
enum Bool { No, Yes };
87+
};
8588
struct IsESM {
8689
enum Bool { No, Yes };
8790
};
8891
const Exists::Bool exists;
8992
const IsValid::Bool is_valid;
9093
const HasMain::Bool has_main;
94+
const HasExports::Bool has_exports;
9195
const std::string main;
9296
const IsESM::Bool esm;
9397
};

src/module_wrap.cc

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ Maybe<std::string> ReadIfFile(const std::string& path) {
524524
using Exists = PackageConfig::Exists;
525525
using IsValid = PackageConfig::IsValid;
526526
using HasMain = PackageConfig::HasMain;
527+
using HasExports = PackageConfig::HasExports;
527528
using IsESM = PackageConfig::IsESM;
528529

529530
Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
@@ -538,8 +539,8 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
538539

539540
if (source.IsNothing()) {
540541
auto entry = env->package_json_cache.emplace(path,
541-
PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "",
542-
IsESM::No });
542+
PackageConfig { Exists::No, IsValid::Yes, HasMain::No, HasExports::No,
543+
"", IsESM::No });
543544
return Just(&entry.first->second);
544545
}
545546

@@ -565,8 +566,8 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
565566

566567
if (!parsed) {
567568
(void)env->package_json_cache.emplace(path,
568-
PackageConfig { Exists::Yes, IsValid::No, HasMain::No, "",
569-
IsESM::No });
569+
PackageConfig { Exists::Yes, IsValid::No, HasMain::No, HasExports::No,
570+
"", IsESM::No });
570571
std::string msg = "Invalid JSON in '" + path +
571572
"' imported from " + base.ToFilePath();
572573
node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
@@ -575,8 +576,17 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
575576

576577
Local<Value> pkg_main;
577578
HasMain::Bool has_main = HasMain::No;
579+
HasExports::Bool has_exports = HasExports::No;
578580
std::string main_std;
579-
if (pkg_json->Get(env->context(), env->main_string()).ToLocal(&pkg_main)) {
581+
if (pkg_json->Get(env->context(), env->exports_string()).ToLocal(&pkg_main)) {
582+
if (pkg_main->IsString()) {
583+
has_main = HasMain::Yes;
584+
has_exports = HasExports::Yes;
585+
}
586+
Utf8Value main_utf8(isolate, pkg_main);
587+
main_std.assign(std::string(*main_utf8, main_utf8.length()));
588+
} else if (pkg_json->Get(env->context(),
589+
env->main_string()).ToLocal(&pkg_main)) {
580590
if (pkg_main->IsString()) {
581591
has_main = HasMain::Yes;
582592
}
@@ -592,24 +602,9 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
592602
}
593603
}
594604

595-
Local<Value> exports_v;
596-
if (pkg_json->Get(env->context(),
597-
env->exports_string()).ToLocal(&exports_v) &&
598-
(exports_v->IsObject() || exports_v->IsString() ||
599-
exports_v->IsBoolean())) {
600-
Persistent<Value> exports;
601-
// esm = IsESM::Yes;
602-
exports.Reset(env->isolate(), exports_v);
603-
604-
auto entry = env->package_json_cache.emplace(path,
605-
PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std,
606-
esm });
607-
return Just(&entry.first->second);
608-
}
609-
610605
auto entry = env->package_json_cache.emplace(path,
611-
PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std,
612-
esm });
606+
PackageConfig { Exists::Yes, IsValid::Yes, has_main, has_exports,
607+
main_std, esm });
613608
return Just(&entry.first->second);
614609
}
615610

@@ -630,8 +625,8 @@ Maybe<const PackageConfig*> GetPackageBoundaryConfig(Environment* env,
630625
// (can't just check "/package.json" for Windows support).
631626
if (pjson_url.path() == last_pjson_url.path()) {
632627
auto entry = env->package_json_cache.emplace(pjson_url.ToFilePath(),
633-
PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "",
634-
IsESM::No });
628+
PackageConfig { Exists::No, IsValid::Yes, HasMain::No,
629+
HasExports::No, "", IsESM::No });
635630
return Just(&entry.first->second);
636631
}
637632
}
@@ -757,15 +752,20 @@ Maybe<ModuleResolution> PackageMainResolve(Environment* env,
757752
node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
758753
return Nothing<ModuleResolution>();
759754
}
760-
if (pcfg.has_main == HasMain::Yes &&
761-
pcfg.main.substr(pcfg.main.length() - 4, 4) == ".mjs") {
762-
return FinalizeResolution(env, URL(pcfg.main, pjson_url), base, true);
763-
}
764-
if (pcfg.esm == IsESM::Yes &&
765-
pcfg.main.substr(pcfg.main.length() - 3, 3) == ".js") {
755+
if (pcfg.has_exports == HasExports::Yes) {
756+
const size_t main_len = pcfg.main.length();
757+
if (main_len > 4 && pcfg.main.substr(main_len - 4, 4) == ".cjs" ||
758+
(pcfg.esm == IsESM::No &&
759+
main_len > 3 && pcfg.main.substr(main_len - 3, 3) == ".js")) {
760+
std::string msg = "Cannot load exports entry point '" +
761+
pcfg.main + "' in " + URL(".", pjson_url).ToFilePath() +
762+
" imported from " + base.ToFilePath() +
763+
" as it would be loaded as CommonJS.";
764+
node::THROW_ERR_FORMAT_MISMATCH(env, msg.c_str());
765+
return Nothing<ModuleResolution>();
766+
}
766767
return FinalizeResolution(env, URL(pcfg.main, pjson_url), base, true);
767768
}
768-
769769
Maybe<URL> resolved = LegacyMainResolve(pjson_url, pcfg);
770770
// Legacy main resolution error
771771
if (resolved.IsNothing()) {

src/node_errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void FatalException(const v8::FunctionCallbackInfo<v8::Value>& args);
6262
V(ERR_STRING_TOO_LONG, Error) \
6363
V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \
6464
V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \
65+
V(ERR_FORMAT_MISMATCH, Error) \
6566

6667
#define V(code, type) \
6768
inline v8::Local<v8::Value> code(v8::Isolate* isolate, \

0 commit comments

Comments
 (0)