1
1
namespace AngleSharp . Scripting . JavaScript
2
2
{
3
- using AngleSharp . Attributes ;
4
- using Jint . Native ;
5
3
using Jint . Native . Object ;
6
4
using Jint . Runtime . Descriptors ;
7
5
using System ;
8
- using System . Collections . Generic ;
9
- using System . Linq ;
10
- using System . Reflection ;
11
6
12
7
sealed class DomNodeInstance : ObjectInstance
13
8
{
14
- readonly Type _type ;
15
- readonly EngineInstance _engine ;
16
- readonly Object _value ;
17
-
18
- PropertyInfo _numericIndexer ;
19
- PropertyInfo _stringIndexer ;
9
+ private readonly EngineInstance _engine ;
10
+ private readonly Object _value ;
20
11
21
12
public DomNodeInstance ( EngineInstance engine , Object value )
22
13
: base ( engine . Jint )
23
14
{
24
- _type = value . GetType ( ) ;
25
15
_engine = engine ;
26
16
_value = value ;
27
-
28
- SetAllMembers ( ) ;
29
- SetPseudoProperties ( ) ;
30
-
31
- // DOM objects can have properties added dynamically
17
+
32
18
Extensible = true ;
33
- Prototype = engine . Jint . Object ;
19
+ Prototype = engine . GetDomPrototype ( value . GetType ( ) ) ;
34
20
}
35
21
36
22
public Object Value
@@ -40,180 +26,21 @@ public Object Value
40
26
41
27
public override String ToString ( )
42
28
{
43
- return String . Format ( "[object {0}]" , _type . Name ) ;
44
- }
45
-
46
- public EngineInstance Context
47
- {
48
- get { return _engine ; }
29
+ return Prototype . ToString ( ) ;
49
30
}
50
31
51
32
public override PropertyDescriptor GetOwnProperty ( String propertyName )
52
33
{
53
- // If we have a numeric indexer and the property is numeric
54
- var numericIndex = default ( Int32 ) ;
34
+ var prototype = Prototype as DomPrototypeInstance ;
35
+ var descriptor = default ( PropertyDescriptor ) ;
36
+ var result = prototype ? . TryGetFromIndex ( _value , propertyName , out descriptor ) ?? false ;
55
37
56
- if ( _numericIndexer != null && Int32 . TryParse ( propertyName , out numericIndex ) )
38
+ if ( ! result )
57
39
{
58
- var args = new Object [ ] { numericIndex } ;
59
-
60
- try
61
- {
62
- var orig = _numericIndexer . GetMethod . Invoke ( _value , args ) ;
63
- var prop = orig . ToJsValue ( _engine ) ;
64
- return new PropertyDescriptor ( prop , false , false , false ) ;
65
- }
66
- catch ( TargetInvocationException ex )
67
- {
68
- if ( ex . InnerException is ArgumentOutOfRangeException )
69
- {
70
- var prop = JsValue . Undefined ;
71
- return new PropertyDescriptor ( prop , false , false , false ) ;
72
- }
73
-
74
- throw ;
75
- }
76
- }
77
-
78
- // Else a string property
79
- // If we have a string indexer and no property exists for this name then use the string indexer
80
- // Jint possibly has a limitation here - if an object has a string indexer. How do we know whether to use the defined indexer or a property?
81
- // Eg. object.callMethod1() vs object['callMethod1'] is not necessarily the same if the object has a string indexer?? (I'm not an ECMA expert!)
82
- // node.attributes is one such object - has both a string and numeric indexer
83
- // This GetOwnProperty override might need an additional parameter to let us know this was called via an indexer
84
- if ( _stringIndexer != null && ! Properties . ContainsKey ( propertyName ) )
85
- {
86
- var args = new Object [ ] { propertyName } ;
87
- var prop = _stringIndexer . GetMethod . Invoke ( _value , args ) . ToJsValue ( _engine ) ;
88
- return new PropertyDescriptor ( prop , false , false , false ) ;
40
+ descriptor = base . GetOwnProperty ( propertyName ) ;
89
41
}
90
42
91
- // Else try to return a registered property
92
- return base . GetOwnProperty ( propertyName ) ;
93
- }
94
-
95
- void SetAllMembers ( )
96
- {
97
- var type = _type ;
98
- var types = new List < Type > ( type . GetTypeInfo ( ) . ImplementedInterfaces ) ;
99
-
100
- do
101
- {
102
- types . Add ( type ) ;
103
- type = type . GetTypeInfo ( ) . BaseType ;
104
- }
105
- while ( type != null ) ;
106
-
107
- SetMembers ( types ) ;
108
- }
109
-
110
- void SetMembers ( IEnumerable < Type > types )
111
- {
112
- foreach ( var type in types )
113
- {
114
- var typeInfo = type . GetTypeInfo ( ) ;
115
- SetProperties ( typeInfo . DeclaredProperties ) ;
116
- SetMethods ( typeInfo . DeclaredMethods ) ;
117
- SetEvents ( typeInfo . DeclaredEvents ) ;
118
- }
119
- }
120
-
121
- void SetEvents ( IEnumerable < EventInfo > eventInfos )
122
- {
123
- foreach ( var eventInfo in eventInfos )
124
- {
125
- var names = eventInfo . GetCustomAttributes < DomNameAttribute > ( ) ;
126
-
127
- foreach ( var name in names . Select ( m => m . OfficialName ) )
128
- {
129
- var eventInstance = new DomEventInstance ( this , eventInfo ) ;
130
- FastSetProperty ( name , new PropertyDescriptor ( eventInstance . Getter , eventInstance . Setter , false , false ) ) ;
131
- }
132
- }
133
- }
134
-
135
- void SetProperties ( IEnumerable < PropertyInfo > properties )
136
- {
137
- foreach ( var property in properties )
138
- {
139
- var index = property . GetCustomAttribute < DomAccessorAttribute > ( ) ;
140
-
141
- if ( index != null )
142
- {
143
- var indexParameters = property . GetIndexParameters ( ) ;
144
-
145
- if ( indexParameters . Length == 1 )
146
- {
147
- if ( indexParameters [ 0 ] . ParameterType == typeof ( Int32 ) )
148
- {
149
- _numericIndexer = property ;
150
- }
151
- else if ( indexParameters [ 0 ] . ParameterType == typeof ( String ) )
152
- {
153
- _stringIndexer = property ;
154
- }
155
- }
156
- }
157
-
158
- var names = property . GetCustomAttributes < DomNameAttribute > ( ) ;
159
-
160
- foreach ( var name in names . Select ( m => m . OfficialName ) )
161
- {
162
- FastSetProperty ( name , new PropertyDescriptor (
163
- new DomFunctionInstance ( _engine , property . GetMethod ) ,
164
- new DomFunctionInstance ( _engine , property . SetMethod ) , false , false ) ) ;
165
- }
166
- }
167
- }
168
-
169
- void SetMethods ( IEnumerable < MethodInfo > methods )
170
- {
171
- foreach ( var method in methods )
172
- {
173
- var names = method . GetCustomAttributes < DomNameAttribute > ( ) ;
174
-
175
- foreach ( var name in names . Select ( m => m . OfficialName ) )
176
- {
177
- //TODO Jint
178
- // If it already has a property with the given name (usually another method),
179
- // then convert that method to a two-layer method, which decides which one
180
- // to pick depending on the number (and probably types) of arguments.
181
- if ( ! Properties . ContainsKey ( name ) )
182
- {
183
- var func = new DomFunctionInstance ( _engine , method ) ;
184
- FastAddProperty ( name , func , false , false , false ) ;
185
- }
186
- }
187
- }
188
- }
189
-
190
- void SetPseudoProperties ( )
191
- {
192
- if ( _type . GetTypeInfo ( ) . ImplementedInterfaces . Contains ( typeof ( AngleSharp . Dom . IElement ) ) )
193
- {
194
- var focusInEventInstance = new DomEventInstance ( this ) ;
195
- var focusOutEventInstance = new DomEventInstance ( this ) ;
196
- var unloadEventInstance = new DomEventInstance ( this ) ;
197
- var contextMenuEventInstance = new DomEventInstance ( this ) ;
198
-
199
- FastSetProperty ( "scrollLeft" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
200
- FastSetProperty ( "scrollTop" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
201
- FastSetProperty ( "scrollWidth" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
202
- FastSetProperty ( "scrollHeight" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
203
- FastSetProperty ( "clientLeft" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
204
- FastSetProperty ( "clientTop" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
205
- FastSetProperty ( "clientWidth" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
206
- FastSetProperty ( "clientHeight" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
207
- FastSetProperty ( "offsetLeft" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
208
- FastSetProperty ( "offsetTop" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
209
- FastSetProperty ( "offsetWidth" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
210
- FastSetProperty ( "offsetHeight" , new PropertyDescriptor ( new JsValue ( 0.0 ) , false , false , false ) ) ;
211
-
212
- FastSetProperty ( "focusin" , new PropertyDescriptor ( focusInEventInstance . Getter , focusInEventInstance . Setter , false , false ) ) ;
213
- FastSetProperty ( "focusout" , new PropertyDescriptor ( focusOutEventInstance . Getter , focusOutEventInstance . Setter , false , false ) ) ;
214
- FastSetProperty ( "unload" , new PropertyDescriptor ( unloadEventInstance . Getter , unloadEventInstance . Setter , false , false ) ) ;
215
- FastSetProperty ( "contextmenu" , new PropertyDescriptor ( contextMenuEventInstance . Getter , contextMenuEventInstance . Setter , false , false ) ) ;
216
- }
43
+ return descriptor ;
217
44
}
218
45
}
219
46
}
0 commit comments