Example #1
0
        public override async Task <Document> LoadDocumentAsync(DocumentSettings settings, DocumentInfo?sourceInfo, string specifier, DocumentCategory category, DocumentContextCallback contextCallback)
        {
            var alias = ResourceModuleUtils.GetResourceAlias(specifier);

            if (alias is object)
            {
                var resource = await _resourceManager.GetResourceAsync(alias);

                if (resource is object)
                {
                    var script = _resourceScriptFactory.CreateFromExtension(resource, Path.GetExtension(alias));

                    if (script is object)
                    {
                        return(new StringDocument(new DocumentInfo(specifier)
                        {
                            Category = ModuleCategory.Standard
                        }, script));
                    }
                }
            }

            throw new FileNotFoundException($"The resource {alias} was not found");

            //return await _defaultLoader.LoadDocumentAsync(settings, sourceInfo, specifier, category, contextCallback);
        }
Example #2
0
        /// <summary>
        ///     User implemented callback to fetch additional imported modules in ES modules.
        /// </summary>
        /// <remarks>
        ///     The callback is invoked on the current runtime execution thread, therefore execution is blocked until
        ///     the callback completes. Notify the host to fetch the dependent module. This is the "import" part
        ///     before HostResolveImportedModule in ES6 spec. This notifies the host that the referencing module has
        ///     the specified module dependency, and the host needs to retrieve the module back.
        ///
        ///     Callback should:
        ///     1. Check if the requested module has been requested before - if yes return the existing
        ///         module record
        ///     2. If no create and initialize a new module record with JsInitializeModuleRecord to
        ///         return and schedule a call to JsParseModuleSource for the new record.
        /// </remarks>
        /// <param name="referencingModule">The referencing module that is requesting the dependent module.</param>
        /// <param name="specifier">The specifier coming from the module source code.</param>
        /// <param name="dependentModuleRecord">The ModuleRecord of the dependent module. If the module was requested
        ///                                     before from other source, return the existing ModuleRecord, otherwise
        ///                                     return a newly created ModuleRecord.</param>
        /// <returns>
        ///     Returns a <c>JsNoError</c> if the operation succeeded an error code otherwise.
        /// </returns>
        /// <see cref="JavaScriptFetchImportedModuleCallBack"/>
        private JavaScriptErrorCode LoadModuleImpl(JavaScriptModuleRecord referencingModule, JavaScriptValue specifier, out JavaScriptModuleRecord dependentModuleRecord)
        {
            var specifierString = specifier.ToString();

            if (_moduleLeases.TryGetValue(specifierString, out var lease))
            {
                dependentModuleRecord = lease.Module;
                return(JavaScriptErrorCode.NoError);
            }

            var alias = ResourceModuleUtils.GetResourceAlias(specifierString);

            if (alias is null)
            {
                dependentModuleRecord           = JavaScriptModuleRecord.Initialize(referencingModule, specifier);
                dependentModuleRecord.HostUrl   = specifierString; // Only for debugging
                dependentModuleRecord.Exception = JavaScriptValue.CreateTypeError($"Failed to resolve module for specifier '{specifierString}'");
                _moduleLeases.Add(specifierString, new ModuleLease(dependentModuleRecord));
                dependentModuleRecord = _moduleLeases[specifierString].Module;
                return(JavaScriptErrorCode.NoError);
            }

            dependentModuleRecord         = JavaScriptModuleRecord.Initialize(referencingModule, specifier);
            dependentModuleRecord.HostUrl = specifierString; // Only for debugging
            _moduleLeases.Add(specifierString, new ModuleLease(dependentModuleRecord));

            // Fire off a task in the threadpool
            Task.Run(async() =>
            {
                var module = _moduleLeases[specifierString].Module;
                try
                {
                    var resource = await _resourceManager.GetResourceAsync(alias);

                    if (resource is object)
                    {
                        var script = _resourceScriptFactory.CreateFromExtension(resource, Path.GetExtension(specifierString));

                        _dispatcher.Invoke(() =>
                        {
                            using (_context.GetScope())
                            {
                                module.ParseSource(script);
                            }
                        });
                    }
                    else
                    {
                        _dispatcher.Invoke(() =>
                        {
                            using (_context.GetScope())
                            {
                                ThrowModuleException(module, JavaScriptValue.CreateError($"Could not find the resource '{specifierString}'"));
                            }
                        });
                    }
                }
                catch (Exception e)
                {
                    _dispatcher.Invoke(() =>
                    {
                        using (_context.GetScope())
                        {
                            ThrowModuleException(module, JavaScriptValue.CreateError(e.Message));
                        }
                    });
                }

                void ThrowModuleException(JavaScriptModuleRecord module, JavaScriptValue error)
                {
                    error.AddRef();
                    module.Exception = error;

                    if (!JavaScriptContext.HasException)
                    {
                        JavaScriptContext.SetException(error);
                    }

                    try
                    {
                        Native.ThrowIfError(JavaScriptErrorCode.ScriptException);
                    }
                    catch (Exception e)
                    {
                        OnResourceLoadError?.Invoke(e);
                    }
                    finally
                    {
                        error.Release();
                    }
                }
            });

            return(JavaScriptErrorCode.NoError);
        }