11namespace AngleSharp . Js
22{
33 using AngleSharp . Dom ;
4+ using AngleSharp . Io ;
5+ using AngleSharp . Text ;
46 using Jint ;
57 using Jint . Native ;
68 using Jint . Native . Object ;
@@ -17,14 +19,20 @@ sealed class EngineInstance
1719 private readonly ReferenceCache _references ;
1820 private readonly IEnumerable < Assembly > _libs ;
1921 private readonly DomNodeInstance _window ;
22+ private readonly JsImportMap _importMap ;
2023
2124 #endregion
2225
2326 #region ctor
2427
2528 public EngineInstance ( IWindow window , IDictionary < String , Object > assignments , IEnumerable < Assembly > libs )
2629 {
27- _engine = new Engine ( ) ;
30+ _importMap = new JsImportMap ( ) ;
31+
32+ _engine = new Engine ( ( options ) =>
33+ {
34+ options . EnableModules ( new JsModuleLoader ( this , window . Document , false ) ) ;
35+ } ) ;
2836 _prototypes = new PrototypeCache ( _engine ) ;
2937 _references = new ReferenceCache ( ) ;
3038 _libs = libs ;
@@ -65,6 +73,8 @@ public EngineInstance(IWindow window, IDictionary<String, Object> assignments, I
6573
6674 public Engine Jint => _engine ;
6775
76+ public JsImportMap ImportMap => _importMap ;
77+
6878 #endregion
6979
7080 #region Methods
@@ -73,14 +83,98 @@ public EngineInstance(IWindow window, IDictionary<String, Object> assignments, I
7383
7484 public ObjectInstance GetDomPrototype ( Type type ) => _prototypes . GetOrCreate ( type , CreatePrototype ) ;
7585
76- public JsValue RunScript ( String source , JsValue context )
86+ public JsValue RunScript ( String source , String type , String sourceUrl , JsValue context )
7787 {
88+ if ( string . IsNullOrEmpty ( type ) )
89+ {
90+ type = MimeTypeNames . DefaultJavaScript ;
91+ }
92+
7893 lock ( _engine )
7994 {
80- return _engine . Evaluate ( source ) ;
95+ if ( MimeTypeNames . IsJavaScript ( type ) )
96+ {
97+ return _engine . Evaluate ( source ) ;
98+ }
99+ else if ( type . Isi ( "importmap" ) )
100+ {
101+ return LoadImportMap ( source ) ;
102+ }
103+ else if ( type . Isi ( "module" ) )
104+ {
105+ // use a unique specifier to import the module into Jint
106+ var specifier = sourceUrl ?? Guid . NewGuid ( ) . ToString ( ) ;
107+
108+ return ImportModule ( specifier , source ) ;
109+ }
110+ else
111+ {
112+ return JsValue . Undefined ;
113+ }
81114 }
82115 }
83116
117+ private JsValue LoadImportMap ( String source )
118+ {
119+ var importMap = _engine . Evaluate ( $ "JSON.parse('{ source } ')") . AsObject ( ) ;
120+
121+ if ( importMap . TryGetValue ( "scopes" , out var scopes ) )
122+ {
123+ var scopesObj = scopes . AsObject ( ) ;
124+
125+ foreach ( var scopeProperty in scopesObj . GetOwnProperties ( ) )
126+ {
127+ var scopePath = scopeProperty . Key . AsString ( ) ;
128+
129+ if ( _importMap . Scopes . ContainsKey ( scopePath ) )
130+ {
131+ continue ;
132+ }
133+
134+ var scopeValue = new Dictionary < string , Uri > ( ) ;
135+
136+ var scopeImports = scopesObj [ scopePath ] . AsObject ( ) ;
137+
138+ foreach ( var scopeImportProperty in scopeImports . GetOwnProperties ( ) )
139+ {
140+ var scopeImportSpecifier = scopeImportProperty . Key . AsString ( ) ;
141+
142+ if ( ! scopeValue . ContainsKey ( scopeImportSpecifier ) )
143+ {
144+ scopeValue . Add ( scopeImportSpecifier , new Uri ( scopeImports [ scopeImportSpecifier ] . AsString ( ) , UriKind . RelativeOrAbsolute ) ) ;
145+ }
146+ }
147+
148+ _importMap . Scopes . Add ( scopePath , scopeValue ) ;
149+ }
150+ }
151+
152+ if ( importMap . TryGetValue ( "imports" , out var imports ) )
153+ {
154+ var importsObj = imports . AsObject ( ) ;
155+
156+ foreach ( var importProperty in importsObj . GetOwnProperties ( ) )
157+ {
158+ var importSpecifier = importProperty . Key . AsString ( ) ;
159+
160+ if ( ! _importMap . Imports . ContainsKey ( importSpecifier ) )
161+ {
162+ _importMap . Imports . Add ( importSpecifier , new Uri ( importsObj [ importSpecifier ] . AsString ( ) , UriKind . RelativeOrAbsolute ) ) ;
163+ }
164+ }
165+ }
166+
167+ return JsValue . Undefined ;
168+ }
169+
170+ private JsValue ImportModule ( String specifier , String source )
171+ {
172+ _engine . Modules . Add ( specifier , source ) ;
173+ _engine . Modules . Import ( specifier ) ;
174+
175+ return JsValue . Undefined ;
176+ }
177+
84178 #endregion
85179
86180 #region Helpers
0 commit comments