1
1
namespace AngleSharp . Js
2
2
{
3
3
using AngleSharp . Dom ;
4
+ using AngleSharp . Io ;
5
+ using AngleSharp . Text ;
4
6
using Jint ;
5
7
using Jint . Native ;
6
8
using Jint . Native . Object ;
@@ -17,14 +19,20 @@ sealed class EngineInstance
17
19
private readonly ReferenceCache _references ;
18
20
private readonly IEnumerable < Assembly > _libs ;
19
21
private readonly DomNodeInstance _window ;
22
+ private readonly JsImportMap _importMap ;
20
23
21
24
#endregion
22
25
23
26
#region ctor
24
27
25
28
public EngineInstance ( IWindow window , IDictionary < String , Object > assignments , IEnumerable < Assembly > libs )
26
29
{
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
+ } ) ;
28
36
_prototypes = new PrototypeCache ( _engine ) ;
29
37
_references = new ReferenceCache ( ) ;
30
38
_libs = libs ;
@@ -65,6 +73,8 @@ public EngineInstance(IWindow window, IDictionary<String, Object> assignments, I
65
73
66
74
public Engine Jint => _engine ;
67
75
76
+ public JsImportMap ImportMap => _importMap ;
77
+
68
78
#endregion
69
79
70
80
#region Methods
@@ -73,14 +83,98 @@ public EngineInstance(IWindow window, IDictionary<String, Object> assignments, I
73
83
74
84
public ObjectInstance GetDomPrototype ( Type type ) => _prototypes . GetOrCreate ( type , CreatePrototype ) ;
75
85
76
- public JsValue RunScript ( String source , JsValue context )
86
+ public JsValue RunScript ( String source , String type , String sourceUrl , JsValue context )
77
87
{
88
+ if ( string . IsNullOrEmpty ( type ) )
89
+ {
90
+ type = MimeTypeNames . DefaultJavaScript ;
91
+ }
92
+
78
93
lock ( _engine )
79
94
{
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
+ }
81
114
}
82
115
}
83
116
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
+
84
178
#endregion
85
179
86
180
#region Helpers
0 commit comments