11namespace AngleSharp . Scripting . JavaScript
22{
3- using AngleSharp . Attributes ;
4- using Jint . Native ;
53 using Jint . Native . Object ;
64 using Jint . Runtime . Descriptors ;
75 using System ;
8- using System . Collections . Generic ;
9- using System . Linq ;
10- using System . Reflection ;
116
127 sealed class DomNodeInstance : ObjectInstance
138 {
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 ;
2011
2112 public DomNodeInstance ( EngineInstance engine , Object value )
2213 : base ( engine . Jint )
2314 {
24- _type = value . GetType ( ) ;
2515 _engine = engine ;
2616 _value = value ;
27-
28- SetAllMembers ( ) ;
29- SetPseudoProperties ( ) ;
30-
31- // DOM objects can have properties added dynamically
17+
3218 Extensible = true ;
33- Prototype = engine . Jint . Object ;
19+ Prototype = engine . GetDomPrototype ( value . GetType ( ) ) ;
3420 }
3521
3622 public Object Value
@@ -40,180 +26,21 @@ public Object Value
4026
4127 public override String ToString ( )
4228 {
43- return String . Format ( "[object {0}]" , _type . Name ) ;
44- }
45-
46- public EngineInstance Context
47- {
48- get { return _engine ; }
29+ return Prototype . ToString ( ) ;
4930 }
5031
5132 public override PropertyDescriptor GetOwnProperty ( String propertyName )
5233 {
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 ;
5537
56- if ( _numericIndexer != null && Int32 . TryParse ( propertyName , out numericIndex ) )
38+ if ( ! result )
5739 {
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 ) ;
8941 }
9042
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 ;
21744 }
21845 }
21946}
0 commit comments