Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
30 changes: 3 additions & 27 deletions Jint/Engine.Modules.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System.Collections.Generic;
using Esprima;
using Esprima.Ast;
using Jint.Runtime;
using Jint.Runtime.Modules;

namespace Jint
{
public partial class Engine
{
public IModuleLoader ModuleLoader { get; internal set; }
internal IModuleLoader ModuleLoader { get; set; }

private readonly Dictionary<ModuleCacheKey, JsModule> _modules = new();

Expand All @@ -23,29 +20,8 @@ internal JsModule LoadModule(string referencingModuleLocation, string specifier)
return module;
}

if (!ModuleLoader.TryLoadModule(specifier, referencingModuleLocation, out var moduleSourceCode, out var moduleLocation))
{
ExceptionHelper.ThrowSyntaxError(Realm, "Error while loading module: module with specifier '" + specifier + "' could not be located");
}

Module moduleSource;
try
{
var parserOptions = new ParserOptions(moduleLocation)
{
AdaptRegexp = true,
Tolerant = true
};

moduleSource = new JavaScriptParser(moduleSourceCode, parserOptions).ParseModule();
}
catch (ParserException ex)
{
ExceptionHelper.ThrowSyntaxError(Realm, "Error while loading module: error in module '" + specifier + "': " + ex.Error?.ToString() ?? ex.Message);
moduleSource = null;
}

module = new JsModule(this, _host.CreateRealm(), moduleSource, moduleLocation, false);
var (loadedModule, location) = ModuleLoader.LoadModule(this, specifier, referencingModuleLocation);
module = new JsModule(this, _host.CreateRealm(), loadedModule, location.AbsoluteUri, false);

_modules[key] = module;

Expand Down
2 changes: 1 addition & 1 deletion Jint/EsprimaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ internal static Record DefineMethod(this ClassProperty m, ObjectInstance obj, Ob

internal static void GetImportEntries(this ImportDeclaration import, List<ImportEntry> importEntries, HashSet<string> requestedModules)
{
var source = import.Source.StringValue;
var source = import.Source.StringValue!;
var specifiers = import.Specifiers;
requestedModules.Add(source!);

Expand Down
9 changes: 0 additions & 9 deletions Jint/Options.Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,5 @@ public static Options WithModuleLoader(this Options options, IModuleLoader modul
options.Modules.ModuleLoader = moduleLoader;
return options;
}

/// <summary>
/// Allows to configure where modules are loaded from.
/// </summary>
public static Options WithModuleSource(this Options options, params IModuleSource[] sources)
{
options.Modules.ModuleSources.AddRange(sources);
return options;
}
}
}
48 changes: 26 additions & 22 deletions Jint/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,32 @@ internal void Apply(Engine engine)
AttachExtensionMethodsToPrototypes(engine);
}

var moduleLoader = Modules.ModuleLoader;
if (Modules.Enabled)
{
engine.ModuleLoader = Modules.ModuleLoader;
engine.ModuleLoader.AddModuleSource(Modules.ModuleSources.Distinct().ToArray());

//Node js like loading of modules
engine.Realm.GlobalObject.SetProperty("require", new PropertyDescriptor(new ClrFunctionInstance(
engine,
"require",
(thisObj, arguments) =>
{
var specifier = TypeConverter.ToString(arguments.At(0));
var module = engine.LoadModule(specifier);
return JsModule.GetModuleNamespace(module);
}),
PropertyFlag.AllForbidden));
}
else
{
engine.ModuleLoader = FailFastModuleLoader.Instance;
if (ReferenceEquals(moduleLoader, FailFastModuleLoader.Instance))
{
moduleLoader = new ModuleLoader(Assembly.GetEntryAssembly().CodeBase);
}

if (Modules.RegisterRequire)
{
// Node js like loading of modules
engine.Realm.GlobalObject.SetProperty("require", new PropertyDescriptor(new ClrFunctionInstance(
engine,
"require",
(thisObj, arguments) =>
{
var specifier = TypeConverter.ToString(arguments.At(0));
var module = engine.LoadModule(specifier);
return JsModule.GetModuleNamespace(module);
}),
PropertyFlag.AllForbidden));
}
}

engine.ModuleLoader = moduleLoader;

// ensure defaults
engine.ClrTypeConverter ??= new DefaultTypeConverter(engine);
}
Expand Down Expand Up @@ -363,13 +367,13 @@ public class ModuleOptions
public bool Enabled { get; set; }

/// <summary>
/// Module loader implementation.
/// Whether to register require function to engine which will delegate to module loader, defaults to false.
/// </summary>
public IModuleLoader ModuleLoader { get; set; } = new DefaultModuleLoader();
public bool RegisterRequire { get; set; }

/// <summary>
/// Module sources for the module loader implementation.
/// Module loader implementation, by default exception will be thrown if module loading is not enabled.
/// </summary>
public List<IModuleSource> ModuleSources { get; } = new();
public IModuleLoader? ModuleLoader { get; set; } = FailFastModuleLoader.Instance;
}
}
96 changes: 0 additions & 96 deletions Jint/Runtime/Modules/DefaultModuleLoader.cs

This file was deleted.

15 changes: 4 additions & 11 deletions Jint/Runtime/Modules/FailFastModuleLoader.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
using System;
#nullable enable

namespace Jint.Runtime.Modules;

internal sealed class FailFastModuleLoader : IModuleLoader
{
public static readonly IModuleLoader Instance = new FailFastModuleLoader();

public bool TryLoadModule(string location, string referencingLocation, out string moduleSource, out string moduleLocation)
{
ThrowDisabledException();
moduleSource = null;
moduleLocation = null;
return false;
}

public void AddModuleSource(params IModuleSource[] moduleSources)
public ModuleLoaderResult LoadModule(Engine engine, string location, string? referencingLocation)
{
ThrowDisabledException();
return default;
}

private static void ThrowDisabledException()
{
throw new InvalidOperationException("Module loading has been disabled, you need to enable it in engine options");
ExceptionHelper.ThrowInvalidOperationException("Module loading has been disabled, you need to enable it in engine options");
}
}
23 changes: 0 additions & 23 deletions Jint/Runtime/Modules/FileModuleSource.cs

This file was deleted.

26 changes: 13 additions & 13 deletions Jint/Runtime/Modules/IModuleLoader.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
namespace Jint.Runtime.Modules;
#nullable enable

using System;
using Esprima.Ast;

namespace Jint.Runtime.Modules;

/// <summary>
/// Module loading result.
/// </summary>
public readonly record struct ModuleLoaderResult(Module Module, Uri Location);

/// <summary>
/// Module loader interface that allows defining how module loadings requests are handled.
/// </summary>
public interface IModuleLoader
{
/// <summary>
/// Tries to load amoudle.
/// </summary>
/// <param name="location"></param>
/// <param name="referencingLocation"></param>
/// <param name="moduleSource"></param>
/// <param name="moduleLocation"></param>
/// <returns></returns>
public bool TryLoadModule(string location, string referencingLocation, out string moduleSource, out string moduleLocation);

/// <summary>
/// Add module loader sources to use. By default Jint only tries to load from local files.
/// Loads a module from given location.
/// </summary>
public void AddModuleSource(params IModuleSource[] moduleSources);
public ModuleLoaderResult LoadModule(Engine engine, string location, string? referencingLocation);
}
14 changes: 0 additions & 14 deletions Jint/Runtime/Modules/IModuleSource.cs

This file was deleted.

Loading