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

Add support for import-maps #500

Open
fuweichin opened this issue Mar 9, 2023 · 2 comments
Open

Add support for import-maps #500

fuweichin opened this issue Mar 9, 2023 · 2 comments

Comments

@fuweichin
Copy link

Now all major browsers, as well as Node.js and Deno, support import-maps natively or with a custom loader. see

Some third party libs, e.g. xpath-analyzer, have used bare module specifiers, to use these libs in ClearScript runtime, currently I need to modify source code, transforming bare module specifiers into relative paths.

@ClearScriptLib ClearScriptLib self-assigned this Mar 9, 2023
@ClearScriptLib
Copy link
Collaborator

Hi @fuweichin,

ClearScript also supports custom loaders. You shouldn't have to modify any source code.

Let's walk through a simple example. Suppose you've installed xpath-analyzer as follows:

> npm install -g xpath-analyzer

Here are the relevant paths (on Windows):

var npmGlobalPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm");
var xpathAnalyzerPath = Path.Combine(npmGlobalPath, "node_modules", "xpath-analyzer");
var xpathLexerPath = Path.Combine(xpathAnalyzerPath, "node_modules", "xpath-lexer");

And here's a custom loader that supports simple mappings:

public class LoaderWithMap : DefaultDocumentLoader {
    private readonly IReadOnlyDictionary<string, string> _map;
    public LoaderWithMap(IDictionary<string, string> map) => _map = new ReadOnlyDictionary<string, string>(map);
    public override Task<Document> LoadDocumentAsync(DocumentSettings settings, DocumentInfo? sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback) {
        if (_map.TryGetValue(specifier, out var replacement)) specifier = replacement;
        return base.LoadDocumentAsync(settings, sourceInfo, specifier, category, contextCallback);
    }
}

You're now ready to set up the script engine:

using var engine = new V8ScriptEngine();
engine.DocumentSettings.AccessFlags = DocumentAccessFlags.EnableFileLoading;
engine.DocumentSettings.Loader = new LoaderWithMap(new Dictionary<string, string> {
    { "xpath-analyzer", Path.Combine(xpathAnalyzerPath, "dist", "xpath_analyzer.esm.js") },
    { "xpath-lexer", Path.Combine(xpathLexerPath, "dist", "xpath_lexer.esm.js") }
});

And run a test script:

engine.AddHostType(typeof(Console));
engine.Execute(new DocumentInfo { Category = ModuleCategory.Standard }, @"
    import XPathAnalyzer from 'xpath-analyzer';
    const analyzer = new XPathAnalyzer('123 + 456');
    Console.WriteLine(JSON.stringify(analyzer.parse(), undefined, 2));
");

The output looks as expected:

{
  "type": "additive",
  "lhs": {
    "type": "number",
    "number": 123
  },
  "rhs": {
    "type": "number",
    "number": 456
  }
}

Please let us know if this approach works for you.

Good luck!

@fuweichin
Copy link
Author

It works.
Thank you!

B.T.W. It would be better to add an example about import-maps to FAQ Tutorial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
2 participants