| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "xfa/fxjse/cfxjse_arguments.h" | 7 #include "xfa/fxjse/cfxjse_arguments.h" |
| 8 #include "xfa/fxjse/class.h" | 8 #include "xfa/fxjse/class.h" |
| 9 #include "xfa/fxjse/value.h" | 9 #include "xfa/fxjse/value.h" |
| 10 | 10 |
| 11 static void FXJSE_DynPropGetterAdapter_MethodCallback( | 11 static void FXJSE_DynPropGetterAdapter_MethodCallback( |
| 12 const v8::FunctionCallbackInfo<v8::Value>& info) { | 12 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 13 v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>(); | 13 v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>(); |
| 14 FXJSE_CLASS* lpClass = static_cast<FXJSE_CLASS*>( | 14 FXJSE_CLASS* lpClass = static_cast<FXJSE_CLASS*>( |
| 15 hCallBackInfo->GetAlignedPointerFromInternalField(0)); | 15 hCallBackInfo->GetAlignedPointerFromInternalField(0)); |
| 16 v8::Local<v8::String> hPropName = | 16 v8::Local<v8::String> hPropName = |
| 17 hCallBackInfo->GetInternalField(1).As<v8::String>(); | 17 hCallBackInfo->GetInternalField(1).As<v8::String>(); |
| 18 ASSERT(lpClass && !hPropName.IsEmpty()); | 18 ASSERT(lpClass && !hPropName.IsEmpty()); |
| 19 v8::String::Utf8Value szPropName(hPropName); | 19 v8::String::Utf8Value szPropName(hPropName); |
| 20 CFX_ByteStringC szFxPropName = *szPropName; | 20 CFX_ByteStringC szFxPropName = *szPropName; |
| 21 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); | 21 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 22 lpThisValue->ForceSetValue(info.This()); | 22 lpThisValue->ForceSetValue(info.This()); |
| 23 CFXJSE_Value* lpRetValue = CFXJSE_Value::Create(info.GetIsolate()); | 23 CFXJSE_Value* lpRetValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 24 CFXJSE_ArgumentsImpl impl = {&info, lpRetValue}; | 24 CFXJSE_ArgumentsImpl impl = {&info, lpRetValue}; |
| 25 lpClass->dynMethodCall(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), | 25 lpClass->dynMethodCall(lpThisValue, szFxPropName, |
| 26 szFxPropName, | |
| 27 reinterpret_cast<CFXJSE_Arguments&>(impl)); | 26 reinterpret_cast<CFXJSE_Arguments&>(impl)); |
| 28 if (!lpRetValue->DirectGetValue().IsEmpty()) { | 27 if (!lpRetValue->DirectGetValue().IsEmpty()) { |
| 29 info.GetReturnValue().Set(lpRetValue->DirectGetValue()); | 28 info.GetReturnValue().Set(lpRetValue->DirectGetValue()); |
| 30 } | 29 } |
| 31 delete lpRetValue; | 30 delete lpRetValue; |
| 32 lpRetValue = nullptr; | 31 lpRetValue = nullptr; |
| 33 delete lpThisValue; | 32 delete lpThisValue; |
| 34 lpThisValue = nullptr; | 33 lpThisValue = nullptr; |
| 35 } | 34 } |
| 36 | 35 |
| 37 static void FXJSE_DynPropGetterAdapter(const FXJSE_CLASS* lpClass, | 36 static void FXJSE_DynPropGetterAdapter(const FXJSE_CLASS* lpClass, |
| 38 FXJSE_HOBJECT hObject, | 37 CFXJSE_Value* pObject, |
| 39 const CFX_ByteStringC& szPropName, | 38 const CFX_ByteStringC& szPropName, |
| 40 FXJSE_HVALUE hValue) { | 39 CFXJSE_Value* pValue) { |
| 41 ASSERT(lpClass); | 40 ASSERT(lpClass); |
| 42 int32_t nPropType = | 41 int32_t nPropType = |
| 43 lpClass->dynPropTypeGetter == nullptr | 42 lpClass->dynPropTypeGetter == nullptr |
| 44 ? FXJSE_ClassPropType_Property | 43 ? FXJSE_ClassPropType_Property |
| 45 : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE); | 44 : lpClass->dynPropTypeGetter(pObject, szPropName, FALSE); |
| 46 if (nPropType == FXJSE_ClassPropType_Property) { | 45 if (nPropType == FXJSE_ClassPropType_Property) { |
| 47 if (lpClass->dynPropGetter) { | 46 if (lpClass->dynPropGetter) { |
| 48 lpClass->dynPropGetter(hObject, szPropName, hValue); | 47 lpClass->dynPropGetter(pObject, szPropName, pValue); |
| 49 } | 48 } |
| 50 } else if (nPropType == FXJSE_ClassPropType_Method) { | 49 } else if (nPropType == FXJSE_ClassPropType_Method) { |
| 51 if (lpClass->dynMethodCall && hValue) { | 50 if (lpClass->dynMethodCall && pValue) { |
| 52 CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue); | 51 v8::Isolate* pIsolate = pValue->GetIsolate(); |
| 53 v8::Isolate* pIsolate = lpValue->GetIsolate(); | |
| 54 v8::HandleScope hscope(pIsolate); | 52 v8::HandleScope hscope(pIsolate); |
| 55 v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate = | 53 v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate = |
| 56 v8::ObjectTemplate::New(pIsolate); | 54 v8::ObjectTemplate::New(pIsolate); |
| 57 hCallBackInfoTemplate->SetInternalFieldCount(2); | 55 hCallBackInfoTemplate->SetInternalFieldCount(2); |
| 58 v8::Local<v8::Object> hCallBackInfo = | 56 v8::Local<v8::Object> hCallBackInfo = |
| 59 hCallBackInfoTemplate->NewInstance(); | 57 hCallBackInfoTemplate->NewInstance(); |
| 60 hCallBackInfo->SetAlignedPointerInInternalField( | 58 hCallBackInfo->SetAlignedPointerInInternalField( |
| 61 0, const_cast<FXJSE_CLASS*>(lpClass)); | 59 0, const_cast<FXJSE_CLASS*>(lpClass)); |
| 62 hCallBackInfo->SetInternalField( | 60 hCallBackInfo->SetInternalField( |
| 63 1, v8::String::NewFromUtf8( | 61 1, v8::String::NewFromUtf8( |
| 64 pIsolate, reinterpret_cast<const char*>(szPropName.raw_str()), | 62 pIsolate, reinterpret_cast<const char*>(szPropName.raw_str()), |
| 65 v8::String::kNormalString, szPropName.GetLength())); | 63 v8::String::kNormalString, szPropName.GetLength())); |
| 66 lpValue->ForceSetValue(v8::Function::New( | 64 pValue->ForceSetValue(v8::Function::New( |
| 67 lpValue->GetIsolate(), FXJSE_DynPropGetterAdapter_MethodCallback, | 65 pValue->GetIsolate(), FXJSE_DynPropGetterAdapter_MethodCallback, |
| 68 hCallBackInfo)); | 66 hCallBackInfo)); |
| 69 } | 67 } |
| 70 } | 68 } |
| 71 } | 69 } |
| 72 | 70 |
| 73 static void FXJSE_DynPropSetterAdapter(const FXJSE_CLASS* lpClass, | 71 static void FXJSE_DynPropSetterAdapter(const FXJSE_CLASS* lpClass, |
| 74 FXJSE_HOBJECT hObject, | 72 CFXJSE_Value* pObject, |
| 75 const CFX_ByteStringC& szPropName, | 73 const CFX_ByteStringC& szPropName, |
| 76 FXJSE_HVALUE hValue) { | 74 CFXJSE_Value* pValue) { |
| 77 ASSERT(lpClass); | 75 ASSERT(lpClass); |
| 78 int32_t nPropType = | 76 int32_t nPropType = |
| 79 lpClass->dynPropTypeGetter == nullptr | 77 lpClass->dynPropTypeGetter == nullptr |
| 80 ? FXJSE_ClassPropType_Property | 78 ? FXJSE_ClassPropType_Property |
| 81 : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE); | 79 : lpClass->dynPropTypeGetter(pObject, szPropName, FALSE); |
| 82 if (nPropType != FXJSE_ClassPropType_Method) { | 80 if (nPropType != FXJSE_ClassPropType_Method) { |
| 83 if (lpClass->dynPropSetter) { | 81 if (lpClass->dynPropSetter) { |
| 84 lpClass->dynPropSetter(hObject, szPropName, hValue); | 82 lpClass->dynPropSetter(pObject, szPropName, pValue); |
| 85 } | 83 } |
| 86 } | 84 } |
| 87 } | 85 } |
| 88 | 86 |
| 89 static FX_BOOL FXJSE_DynPropQueryAdapter(const FXJSE_CLASS* lpClass, | 87 static FX_BOOL FXJSE_DynPropQueryAdapter(const FXJSE_CLASS* lpClass, |
| 90 FXJSE_HOBJECT hObject, | 88 CFXJSE_Value* pObject, |
| 91 const CFX_ByteStringC& szPropName) { | 89 const CFX_ByteStringC& szPropName) { |
| 92 ASSERT(lpClass); | 90 ASSERT(lpClass); |
| 93 int32_t nPropType = | 91 int32_t nPropType = |
| 94 lpClass->dynPropTypeGetter == nullptr | 92 lpClass->dynPropTypeGetter == nullptr |
| 95 ? FXJSE_ClassPropType_Property | 93 ? FXJSE_ClassPropType_Property |
| 96 : lpClass->dynPropTypeGetter(hObject, szPropName, TRUE); | 94 : lpClass->dynPropTypeGetter(pObject, szPropName, TRUE); |
| 97 return nPropType != FXJSE_ClassPropType_None; | 95 return nPropType != FXJSE_ClassPropType_None; |
| 98 } | 96 } |
| 99 | 97 |
| 100 static FX_BOOL FXJSE_DynPropDeleterAdapter(const FXJSE_CLASS* lpClass, | 98 static FX_BOOL FXJSE_DynPropDeleterAdapter(const FXJSE_CLASS* lpClass, |
| 101 FXJSE_HOBJECT hObject, | 99 CFXJSE_Value* pObject, |
| 102 const CFX_ByteStringC& szPropName) { | 100 const CFX_ByteStringC& szPropName) { |
| 103 ASSERT(lpClass); | 101 ASSERT(lpClass); |
| 104 int32_t nPropType = | 102 int32_t nPropType = |
| 105 lpClass->dynPropTypeGetter == nullptr | 103 lpClass->dynPropTypeGetter == nullptr |
| 106 ? FXJSE_ClassPropType_Property | 104 ? FXJSE_ClassPropType_Property |
| 107 : lpClass->dynPropTypeGetter(hObject, szPropName, FALSE); | 105 : lpClass->dynPropTypeGetter(pObject, szPropName, FALSE); |
| 108 if (nPropType != FXJSE_ClassPropType_Method) { | 106 if (nPropType != FXJSE_ClassPropType_Method) { |
| 109 if (lpClass->dynPropDeleter) { | 107 if (lpClass->dynPropDeleter) { |
| 110 return lpClass->dynPropDeleter(hObject, szPropName); | 108 return lpClass->dynPropDeleter(pObject, szPropName); |
| 111 } else { | 109 } else { |
| 112 return nPropType == FXJSE_ClassPropType_Property ? FALSE : TRUE; | 110 return nPropType == FXJSE_ClassPropType_Property ? FALSE : TRUE; |
| 113 } | 111 } |
| 114 } | 112 } |
| 115 return FALSE; | 113 return FALSE; |
| 116 } | 114 } |
| 117 | 115 |
| 118 static void FXJSE_V8_GenericNamedPropertyQueryCallback( | 116 static void FXJSE_V8_GenericNamedPropertyQueryCallback( |
| 119 v8::Local<v8::Name> property, | 117 v8::Local<v8::Name> property, |
| 120 const v8::PropertyCallbackInfo<v8::Integer>& info) { | 118 const v8::PropertyCallbackInfo<v8::Integer>& info) { |
| 121 v8::Local<v8::Object> thisObject = info.This(); | 119 v8::Local<v8::Object> thisObject = info.This(); |
| 122 const FXJSE_CLASS* lpClass = | 120 const FXJSE_CLASS* lpClass = |
| 123 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); | 121 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); |
| 124 v8::Isolate* pIsolate = info.GetIsolate(); | 122 v8::Isolate* pIsolate = info.GetIsolate(); |
| 125 v8::HandleScope scope(pIsolate); | 123 v8::HandleScope scope(pIsolate); |
| 126 v8::String::Utf8Value szPropName(property); | 124 v8::String::Utf8Value szPropName(property); |
| 127 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); | 125 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); |
| 128 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); | 126 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 129 lpThisValue->ForceSetValue(thisObject); | 127 lpThisValue->ForceSetValue(thisObject); |
| 130 if (FXJSE_DynPropQueryAdapter(lpClass, | 128 if (FXJSE_DynPropQueryAdapter(lpClass, lpThisValue, szFxPropName)) { |
| 131 reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), | |
| 132 szFxPropName)) { | |
| 133 info.GetReturnValue().Set(v8::DontDelete); | 129 info.GetReturnValue().Set(v8::DontDelete); |
| 134 } else { | 130 } else { |
| 135 const int32_t iV8Absent = 64; | 131 const int32_t iV8Absent = 64; |
| 136 info.GetReturnValue().Set(iV8Absent); | 132 info.GetReturnValue().Set(iV8Absent); |
| 137 } | 133 } |
| 138 delete lpThisValue; | 134 delete lpThisValue; |
| 139 lpThisValue = nullptr; | 135 lpThisValue = nullptr; |
| 140 } | 136 } |
| 141 | 137 |
| 142 static void FXJSE_V8_GenericNamedPropertyDeleterCallback( | 138 static void FXJSE_V8_GenericNamedPropertyDeleterCallback( |
| 143 v8::Local<v8::Name> property, | 139 v8::Local<v8::Name> property, |
| 144 const v8::PropertyCallbackInfo<v8::Boolean>& info) { | 140 const v8::PropertyCallbackInfo<v8::Boolean>& info) { |
| 145 v8::Local<v8::Object> thisObject = info.This(); | 141 v8::Local<v8::Object> thisObject = info.This(); |
| 146 const FXJSE_CLASS* lpClass = | 142 const FXJSE_CLASS* lpClass = |
| 147 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); | 143 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); |
| 148 v8::Isolate* pIsolate = info.GetIsolate(); | 144 v8::Isolate* pIsolate = info.GetIsolate(); |
| 149 v8::HandleScope scope(pIsolate); | 145 v8::HandleScope scope(pIsolate); |
| 150 v8::String::Utf8Value szPropName(property); | 146 v8::String::Utf8Value szPropName(property); |
| 151 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); | 147 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); |
| 152 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); | 148 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 153 lpThisValue->ForceSetValue(thisObject); | 149 lpThisValue->ForceSetValue(thisObject); |
| 154 info.GetReturnValue().Set( | 150 info.GetReturnValue().Set( |
| 155 FXJSE_DynPropDeleterAdapter( | 151 !!FXJSE_DynPropDeleterAdapter(lpClass, lpThisValue, szFxPropName)); |
| 156 lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName) | |
| 157 ? true | |
| 158 : false); | |
| 159 delete lpThisValue; | 152 delete lpThisValue; |
| 160 lpThisValue = nullptr; | 153 lpThisValue = nullptr; |
| 161 } | 154 } |
| 162 | 155 |
| 163 static void FXJSE_V8_GenericNamedPropertyGetterCallback( | 156 static void FXJSE_V8_GenericNamedPropertyGetterCallback( |
| 164 v8::Local<v8::Name> property, | 157 v8::Local<v8::Name> property, |
| 165 const v8::PropertyCallbackInfo<v8::Value>& info) { | 158 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 166 v8::Local<v8::Object> thisObject = info.This(); | 159 v8::Local<v8::Object> thisObject = info.This(); |
| 167 const FXJSE_CLASS* lpClass = | 160 const FXJSE_CLASS* lpClass = |
| 168 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); | 161 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); |
| 169 v8::String::Utf8Value szPropName(property); | 162 v8::String::Utf8Value szPropName(property); |
| 170 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); | 163 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); |
| 171 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); | 164 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 172 lpThisValue->ForceSetValue(thisObject); | 165 lpThisValue->ForceSetValue(thisObject); |
| 173 CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate()); | 166 CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 174 FXJSE_DynPropGetterAdapter( | 167 FXJSE_DynPropGetterAdapter(lpClass, lpThisValue, szFxPropName, lpNewValue); |
| 175 lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName, | |
| 176 reinterpret_cast<FXJSE_HVALUE>(lpNewValue)); | |
| 177 info.GetReturnValue().Set(lpNewValue->DirectGetValue()); | 168 info.GetReturnValue().Set(lpNewValue->DirectGetValue()); |
| 178 delete lpThisValue; | 169 delete lpThisValue; |
| 179 lpThisValue = nullptr; | 170 lpThisValue = nullptr; |
| 180 } | 171 } |
| 181 | 172 |
| 182 static void FXJSE_V8_GenericNamedPropertySetterCallback( | 173 static void FXJSE_V8_GenericNamedPropertySetterCallback( |
| 183 v8::Local<v8::Name> property, | 174 v8::Local<v8::Name> property, |
| 184 v8::Local<v8::Value> value, | 175 v8::Local<v8::Value> value, |
| 185 const v8::PropertyCallbackInfo<v8::Value>& info) { | 176 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 186 v8::Local<v8::Object> thisObject = info.This(); | 177 v8::Local<v8::Object> thisObject = info.This(); |
| 187 const FXJSE_CLASS* lpClass = | 178 const FXJSE_CLASS* lpClass = |
| 188 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); | 179 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); |
| 189 v8::String::Utf8Value szPropName(property); | 180 v8::String::Utf8Value szPropName(property); |
| 190 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); | 181 CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); |
| 191 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); | 182 CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 192 lpThisValue->ForceSetValue(thisObject); | 183 lpThisValue->ForceSetValue(thisObject); |
| 193 CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate()); | 184 CFXJSE_Value* lpNewValue = CFXJSE_Value::Create(info.GetIsolate()); |
| 194 lpNewValue->ForceSetValue(value); | 185 lpNewValue->ForceSetValue(value); |
| 195 FXJSE_DynPropSetterAdapter( | 186 FXJSE_DynPropSetterAdapter(lpClass, lpThisValue, szFxPropName, lpNewValue); |
| 196 lpClass, reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), szFxPropName, | |
| 197 reinterpret_cast<FXJSE_HVALUE>(lpNewValue)); | |
| 198 info.GetReturnValue().Set(value); | 187 info.GetReturnValue().Set(value); |
| 199 delete lpThisValue; | 188 delete lpThisValue; |
| 200 lpThisValue = nullptr; | 189 lpThisValue = nullptr; |
| 201 } | 190 } |
| 202 | 191 |
| 203 static void FXJSE_V8_GenericNamedPropertyEnumeratorCallback( | 192 static void FXJSE_V8_GenericNamedPropertyEnumeratorCallback( |
| 204 const v8::PropertyCallbackInfo<v8::Array>& info) { | 193 const v8::PropertyCallbackInfo<v8::Array>& info) { |
| 205 const FXJSE_CLASS* lpClass = | 194 const FXJSE_CLASS* lpClass = |
| 206 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); | 195 static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); |
| 207 v8::Isolate* pIsolate = info.GetIsolate(); | 196 v8::Isolate* pIsolate = info.GetIsolate(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 228 ? FXJSE_V8_GenericNamedPropertyQueryCallback | 217 ? FXJSE_V8_GenericNamedPropertyQueryCallback |
| 229 : 0, | 218 : 0, |
| 230 lpClassDefinition->dynPropDeleter | 219 lpClassDefinition->dynPropDeleter |
| 231 ? FXJSE_V8_GenericNamedPropertyDeleterCallback | 220 ? FXJSE_V8_GenericNamedPropertyDeleterCallback |
| 232 : 0, | 221 : 0, |
| 233 FXJSE_V8_GenericNamedPropertyEnumeratorCallback, | 222 FXJSE_V8_GenericNamedPropertyEnumeratorCallback, |
| 234 v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(lpClassDefinition)), | 223 v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(lpClassDefinition)), |
| 235 v8::PropertyHandlerFlags::kNonMasking); | 224 v8::PropertyHandlerFlags::kNonMasking); |
| 236 hObjectTemplate->SetHandler(configuration); | 225 hObjectTemplate->SetHandler(configuration); |
| 237 } | 226 } |
| OLD | NEW |