as_objecttype.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2017 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_objecttype.cpp
  25. //
  26. // A class for storing object type information
  27. //
  28. #include <stdio.h>
  29. #include "as_config.h"
  30. #include "as_objecttype.h"
  31. #include "as_configgroup.h"
  32. #include "as_scriptengine.h"
  33. BEGIN_AS_NAMESPACE
  34. asCObjectType::asCObjectType() : asCTypeInfo()
  35. {
  36. derivedFrom = 0;
  37. acceptValueSubType = true;
  38. acceptRefSubType = true;
  39. #ifdef WIP_16BYTE_ALIGN
  40. alignment = 4;
  41. #endif
  42. }
  43. asCObjectType::asCObjectType(asCScriptEngine *in_engine) : asCTypeInfo(in_engine)
  44. {
  45. derivedFrom = 0;
  46. acceptValueSubType = true;
  47. acceptRefSubType = true;
  48. #ifdef WIP_16BYTE_ALIGN
  49. alignment = 4;
  50. #endif
  51. }
  52. // interface
  53. asUINT asCObjectType::GetChildFuncdefCount() const
  54. {
  55. return childFuncDefs.GetLength();
  56. }
  57. // interface
  58. asITypeInfo *asCObjectType::GetChildFuncdef(asUINT index) const
  59. {
  60. if (index >= childFuncDefs.GetLength())
  61. return 0;
  62. return childFuncDefs[index];
  63. }
  64. // internal
  65. void asCObjectType::DestroyInternal()
  66. {
  67. if( engine == 0 ) return;
  68. // Skip this for list patterns as they do not increase the references
  69. if( flags & asOBJ_LIST_PATTERN )
  70. {
  71. // Clear the engine pointer to mark the object type as invalid
  72. engine = 0;
  73. return;
  74. }
  75. // Release the object types held by the templateSubTypes
  76. bool isTemplateInstance = templateSubTypes.GetLength() > 0;
  77. for( asUINT subtypeIndex = 0; subtypeIndex < templateSubTypes.GetLength(); subtypeIndex++ )
  78. {
  79. if( templateSubTypes[subtypeIndex].GetTypeInfo() )
  80. templateSubTypes[subtypeIndex].GetTypeInfo()->ReleaseInternal();
  81. }
  82. templateSubTypes.SetLength(0);
  83. // Clear the child types
  84. for (asUINT n = 0; n < childFuncDefs.GetLength(); n++)
  85. {
  86. asCFuncdefType *func = childFuncDefs[n];
  87. if (func)
  88. {
  89. func->parentClass = 0;
  90. if (isTemplateInstance)
  91. {
  92. // Any child funcdefs that have been created as part of the template
  93. // instantiation must be destroyed too
  94. // TODO: Before destroying the funcdef, make sure no external references to it is held
  95. if (func->externalRefCount.get() == 0)
  96. {
  97. func->DestroyInternal();
  98. engine->RemoveFuncdef(func);
  99. func->module = 0;
  100. func->ReleaseInternal();
  101. }
  102. }
  103. }
  104. }
  105. childFuncDefs.SetLength(0);
  106. if( derivedFrom )
  107. derivedFrom->ReleaseInternal();
  108. derivedFrom = 0;
  109. ReleaseAllProperties();
  110. ReleaseAllFunctions();
  111. CleanUserData();
  112. // Remove the type from the engine
  113. if( typeId != -1 )
  114. engine->RemoveFromTypeIdMap(this);
  115. // Clear the engine pointer to mark the object type as invalid
  116. engine = 0;
  117. }
  118. asCObjectType::~asCObjectType()
  119. {
  120. DestroyInternal();
  121. }
  122. // interface
  123. bool asCObjectType::Implements(const asITypeInfo *objType) const
  124. {
  125. if( this == objType )
  126. return true;
  127. for( asUINT n = 0; n < interfaces.GetLength(); n++ )
  128. if( interfaces[n] == objType ) return true;
  129. return false;
  130. }
  131. // interface
  132. bool asCObjectType::DerivesFrom(const asITypeInfo *objType) const
  133. {
  134. if( this == objType )
  135. return true;
  136. asCObjectType *base = derivedFrom;
  137. while( base )
  138. {
  139. if( base == objType )
  140. return true;
  141. base = base->derivedFrom;
  142. }
  143. return false;
  144. }
  145. // interface
  146. int asCObjectType::GetSubTypeId(asUINT subtypeIndex) const
  147. {
  148. // This method is only supported for templates and template specializations
  149. if( templateSubTypes.GetLength() == 0 )
  150. return asERROR;
  151. if( subtypeIndex >= templateSubTypes.GetLength() )
  152. return asINVALID_ARG;
  153. return engine->GetTypeIdFromDataType(templateSubTypes[subtypeIndex]);
  154. }
  155. // interface
  156. asITypeInfo *asCObjectType::GetSubType(asUINT subtypeIndex) const
  157. {
  158. if( subtypeIndex >= templateSubTypes.GetLength() )
  159. return 0;
  160. return templateSubTypes[subtypeIndex].GetTypeInfo();
  161. }
  162. asUINT asCObjectType::GetSubTypeCount() const
  163. {
  164. return asUINT(templateSubTypes.GetLength());
  165. }
  166. asUINT asCObjectType::GetInterfaceCount() const
  167. {
  168. return asUINT(interfaces.GetLength());
  169. }
  170. asITypeInfo *asCObjectType::GetInterface(asUINT index) const
  171. {
  172. return interfaces[index];
  173. }
  174. // internal
  175. bool asCObjectType::IsInterface() const
  176. {
  177. if( (flags & asOBJ_SCRIPT_OBJECT) && size == 0 )
  178. return true;
  179. return false;
  180. }
  181. // interface
  182. asUINT asCObjectType::GetFactoryCount() const
  183. {
  184. return (asUINT)beh.factories.GetLength();
  185. }
  186. // interface
  187. asIScriptFunction *asCObjectType::GetFactoryByIndex(asUINT index) const
  188. {
  189. if( index >= beh.factories.GetLength() )
  190. return 0;
  191. return engine->GetFunctionById(beh.factories[index]);
  192. }
  193. // interface
  194. asIScriptFunction *asCObjectType::GetFactoryByDecl(const char *decl) const
  195. {
  196. if( beh.factories.GetLength() == 0 )
  197. return 0;
  198. // Let the engine parse the string and find the appropriate factory function
  199. return engine->GetFunctionById(engine->GetFactoryIdByDecl(this, decl));
  200. }
  201. // interface
  202. asUINT asCObjectType::GetMethodCount() const
  203. {
  204. return (asUINT)methods.GetLength();
  205. }
  206. // interface
  207. asIScriptFunction *asCObjectType::GetMethodByIndex(asUINT index, bool getVirtual) const
  208. {
  209. if( index >= methods.GetLength() )
  210. return 0;
  211. asCScriptFunction *func = engine->scriptFunctions[methods[index]];
  212. if( !getVirtual )
  213. {
  214. if( func && func->funcType == asFUNC_VIRTUAL )
  215. return virtualFunctionTable[func->vfTableIdx];
  216. }
  217. return func;
  218. }
  219. // interface
  220. asIScriptFunction *asCObjectType::GetMethodByName(const char *in_name, bool in_getVirtual) const
  221. {
  222. int id = -1;
  223. for( asUINT n = 0; n < methods.GetLength(); n++ )
  224. {
  225. if( engine->scriptFunctions[methods[n]]->name == in_name )
  226. {
  227. if( id == -1 )
  228. id = methods[n];
  229. else
  230. return 0;
  231. }
  232. }
  233. if( id == -1 ) return 0;
  234. asCScriptFunction *func = engine->scriptFunctions[id];
  235. if( !in_getVirtual )
  236. {
  237. if( func && func->funcType == asFUNC_VIRTUAL )
  238. return virtualFunctionTable[func->vfTableIdx];
  239. }
  240. return func;
  241. }
  242. // interface
  243. asIScriptFunction *asCObjectType::GetMethodByDecl(const char *decl, bool getVirtual) const
  244. {
  245. if( methods.GetLength() == 0 )
  246. return 0;
  247. // Get the module from one of the methods, but it will only be
  248. // used to allow the parsing of types not already known by the object.
  249. // It is possible for object types to be orphaned, e.g. by discarding
  250. // the module that created it. In this case it is still possible to
  251. // find the methods, but any type not known by the object will result in
  252. // an invalid declaration.
  253. asCModule *mod = engine->scriptFunctions[methods[0]]->module;
  254. int id = engine->GetMethodIdByDecl(this, decl, mod);
  255. if( id <= 0 )
  256. return 0;
  257. if( !getVirtual )
  258. {
  259. asCScriptFunction *func = engine->scriptFunctions[id];
  260. if( func && func->funcType == asFUNC_VIRTUAL )
  261. return virtualFunctionTable[func->vfTableIdx];
  262. }
  263. return engine->scriptFunctions[id];
  264. }
  265. // interface
  266. asUINT asCObjectType::GetPropertyCount() const
  267. {
  268. return (asUINT)properties.GetLength();
  269. }
  270. // interface
  271. int asCObjectType::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const
  272. {
  273. if( index >= properties.GetLength() )
  274. return asINVALID_ARG;
  275. asCObjectProperty *prop = properties[index];
  276. if( out_name )
  277. *out_name = prop->name.AddressOf();
  278. if( out_typeId )
  279. *out_typeId = engine->GetTypeIdFromDataType(prop->type);
  280. if( out_isPrivate )
  281. *out_isPrivate = prop->isPrivate;
  282. if( out_isProtected )
  283. *out_isProtected = prop->isProtected;
  284. if( out_offset )
  285. *out_offset = prop->byteOffset;
  286. if( out_isReference )
  287. *out_isReference = prop->type.IsReference();
  288. if( out_accessMask )
  289. *out_accessMask = prop->accessMask;
  290. if (out_compositeOffset)
  291. *out_compositeOffset = prop->compositeOffset;
  292. if (out_isCompositeIndirect)
  293. *out_isCompositeIndirect = prop->isCompositeIndirect;
  294. return 0;
  295. }
  296. // interface
  297. const char *asCObjectType::GetPropertyDeclaration(asUINT index, bool includeNamespace) const
  298. {
  299. if( index >= properties.GetLength() )
  300. return 0;
  301. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  302. if( properties[index]->isPrivate )
  303. *tempString = "private ";
  304. else if( properties[index]->isProtected )
  305. *tempString = "protected ";
  306. else
  307. *tempString = "";
  308. *tempString += properties[index]->type.Format(nameSpace, includeNamespace);
  309. *tempString += " ";
  310. *tempString += properties[index]->name;
  311. return tempString->AddressOf();
  312. }
  313. asITypeInfo *asCObjectType::GetBaseType() const
  314. {
  315. return derivedFrom;
  316. }
  317. asUINT asCObjectType::GetBehaviourCount() const
  318. {
  319. // Count the number of behaviours (except factory functions)
  320. asUINT count = 0;
  321. if( beh.destruct ) count++;
  322. if( beh.addref ) count++;
  323. if( beh.release ) count++;
  324. if( beh.gcGetRefCount ) count++;
  325. if( beh.gcSetFlag ) count++;
  326. if( beh.gcGetFlag ) count++;
  327. if( beh.gcEnumReferences ) count++;
  328. if( beh.gcReleaseAllReferences ) count++;
  329. if( beh.templateCallback ) count++;
  330. if( beh.listFactory ) count++;
  331. if( beh.getWeakRefFlag ) count++;
  332. // For reference types, the factories are also stored in the constructor
  333. // list, so it is sufficient to enumerate only those
  334. count += (asUINT)beh.constructors.GetLength();
  335. return count;
  336. }
  337. asIScriptFunction *asCObjectType::GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const
  338. {
  339. // Find the correct behaviour
  340. asUINT count = 0;
  341. if( beh.destruct && count++ == index ) // only increase count if the behaviour is registered
  342. {
  343. if( outBehaviour ) *outBehaviour = asBEHAVE_DESTRUCT;
  344. return engine->scriptFunctions[beh.destruct];
  345. }
  346. if( beh.addref && count++ == index )
  347. {
  348. if( outBehaviour ) *outBehaviour = asBEHAVE_ADDREF;
  349. return engine->scriptFunctions[beh.addref];
  350. }
  351. if( beh.release && count++ == index )
  352. {
  353. if( outBehaviour ) *outBehaviour = asBEHAVE_RELEASE;
  354. return engine->scriptFunctions[beh.release];
  355. }
  356. if( beh.gcGetRefCount && count++ == index )
  357. {
  358. if( outBehaviour ) *outBehaviour = asBEHAVE_GETREFCOUNT;
  359. return engine->scriptFunctions[beh.gcGetRefCount];
  360. }
  361. if( beh.gcSetFlag && count++ == index )
  362. {
  363. if( outBehaviour ) *outBehaviour = asBEHAVE_SETGCFLAG;
  364. return engine->scriptFunctions[beh.gcSetFlag];
  365. }
  366. if( beh.gcGetFlag && count++ == index )
  367. {
  368. if( outBehaviour ) *outBehaviour = asBEHAVE_GETGCFLAG;
  369. return engine->scriptFunctions[beh.gcGetFlag];
  370. }
  371. if( beh.gcEnumReferences && count++ == index )
  372. {
  373. if( outBehaviour ) *outBehaviour = asBEHAVE_ENUMREFS;
  374. return engine->scriptFunctions[beh.gcEnumReferences];
  375. }
  376. if( beh.gcReleaseAllReferences && count++ == index )
  377. {
  378. if( outBehaviour ) *outBehaviour = asBEHAVE_RELEASEREFS;
  379. return engine->scriptFunctions[beh.gcReleaseAllReferences];
  380. }
  381. if( beh.templateCallback && count++ == index )
  382. {
  383. if( outBehaviour ) *outBehaviour = asBEHAVE_TEMPLATE_CALLBACK;
  384. return engine->scriptFunctions[beh.templateCallback];
  385. }
  386. if( beh.listFactory && count++ == index )
  387. {
  388. if( outBehaviour )
  389. {
  390. if( flags & asOBJ_VALUE )
  391. *outBehaviour = asBEHAVE_LIST_CONSTRUCT;
  392. else
  393. *outBehaviour = asBEHAVE_LIST_FACTORY;
  394. }
  395. return engine->scriptFunctions[beh.listFactory];
  396. }
  397. if( beh.getWeakRefFlag && count++ == index )
  398. {
  399. if( outBehaviour ) *outBehaviour = asBEHAVE_GET_WEAKREF_FLAG;
  400. return engine->scriptFunctions[beh.getWeakRefFlag];
  401. }
  402. // For reference types, the factories are also stored in the constructor
  403. // list, so it is sufficient to enumerate only those
  404. if( index - count < beh.constructors.GetLength() )
  405. {
  406. if( outBehaviour ) *outBehaviour = asBEHAVE_CONSTRUCT;
  407. return engine->scriptFunctions[beh.constructors[index - count]];
  408. }
  409. else
  410. count += (asUINT)beh.constructors.GetLength();
  411. return 0;
  412. }
  413. // internal
  414. asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &propName, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited)
  415. {
  416. asASSERT( flags & asOBJ_SCRIPT_OBJECT );
  417. asASSERT( dt.CanBeInstantiated() );
  418. asASSERT( !IsInterface() );
  419. // Store the properties in the object type descriptor
  420. asCObjectProperty *prop = asNEW(asCObjectProperty);
  421. if( prop == 0 )
  422. {
  423. // Out of memory
  424. return 0;
  425. }
  426. prop->name = propName;
  427. prop->type = dt;
  428. prop->isPrivate = isPrivate;
  429. prop->isProtected = isProtected;
  430. prop->isInherited = isInherited;
  431. int propSize;
  432. if( dt.IsObject() )
  433. {
  434. // Non-POD value types can't be allocated inline,
  435. // because there is a risk that the script might
  436. // try to access the content without knowing that
  437. // it hasn't been initialized yet.
  438. if( dt.GetTypeInfo()->flags & asOBJ_POD )
  439. propSize = dt.GetSizeInMemoryBytes();
  440. else
  441. {
  442. propSize = dt.GetSizeOnStackDWords()*4;
  443. if( !dt.IsObjectHandle() )
  444. prop->type.MakeReference(true);
  445. }
  446. }
  447. else if (dt.IsFuncdef())
  448. {
  449. // Funcdefs don't have a size, as they must always be stored as handles
  450. asASSERT(dt.IsObjectHandle());
  451. propSize = AS_PTR_SIZE * 4;
  452. }
  453. else
  454. propSize = dt.GetSizeInMemoryBytes();
  455. // Add extra bytes so that the property will be properly aligned
  456. #ifndef WIP_16BYTE_ALIGN
  457. if( propSize == 2 && (size & 1) ) size += 1;
  458. if( propSize > 2 && (size & 3) ) size += 4 - (size & 3);
  459. #else
  460. asUINT alignment = dt.GetAlignment();
  461. const asUINT propSizeAlignmentDifference = size & (alignment-1);
  462. if( propSizeAlignmentDifference != 0 )
  463. {
  464. size += (alignment - propSizeAlignmentDifference);
  465. }
  466. asASSERT((size % alignment) == 0);
  467. #endif
  468. prop->byteOffset = size;
  469. size += propSize;
  470. properties.PushLast(prop);
  471. // Make sure the struct holds a reference to the config group where the object is registered
  472. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(prop->type.GetTypeInfo());
  473. if( group != 0 ) group->AddRef();
  474. // Add reference to object types
  475. asCTypeInfo *type = prop->type.GetTypeInfo();
  476. if( type )
  477. type->AddRefInternal();
  478. return prop;
  479. }
  480. // internal
  481. void asCObjectType::ReleaseAllProperties()
  482. {
  483. for( asUINT n = 0; n < properties.GetLength(); n++ )
  484. {
  485. if( properties[n] )
  486. {
  487. if( flags & asOBJ_SCRIPT_OBJECT )
  488. {
  489. // Release the config group for script classes that are being destroyed
  490. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(properties[n]->type.GetTypeInfo());
  491. if( group != 0 ) group->Release();
  492. // Release references to objects types
  493. asCTypeInfo *type = properties[n]->type.GetTypeInfo();
  494. if( type )
  495. type->ReleaseInternal();
  496. }
  497. else
  498. {
  499. // Release template instance types (ref increased by RegisterObjectProperty)
  500. asCTypeInfo *type = properties[n]->type.GetTypeInfo();
  501. if( type )
  502. type->ReleaseInternal();
  503. }
  504. asDELETE(properties[n],asCObjectProperty);
  505. }
  506. }
  507. properties.SetLength(0);
  508. }
  509. // internal
  510. void asCObjectType::ReleaseAllFunctions()
  511. {
  512. beh.factory = 0;
  513. beh.copyfactory = 0;
  514. for( asUINT a = 0; a < beh.factories.GetLength(); a++ )
  515. {
  516. if( engine->scriptFunctions[beh.factories[a]] )
  517. engine->scriptFunctions[beh.factories[a]]->ReleaseInternal();
  518. }
  519. beh.factories.SetLength(0);
  520. beh.construct = 0;
  521. beh.copyconstruct = 0;
  522. for( asUINT b = 0; b < beh.constructors.GetLength(); b++ )
  523. {
  524. if( engine->scriptFunctions[beh.constructors[b]] )
  525. engine->scriptFunctions[beh.constructors[b]]->ReleaseInternal();
  526. }
  527. beh.constructors.SetLength(0);
  528. if( beh.templateCallback )
  529. engine->scriptFunctions[beh.templateCallback]->ReleaseInternal();
  530. beh.templateCallback = 0;
  531. if( beh.listFactory )
  532. engine->scriptFunctions[beh.listFactory]->ReleaseInternal();
  533. beh.listFactory = 0;
  534. if( beh.destruct )
  535. engine->scriptFunctions[beh.destruct]->ReleaseInternal();
  536. beh.destruct = 0;
  537. if( beh.copy )
  538. engine->scriptFunctions[beh.copy]->ReleaseInternal();
  539. beh.copy = 0;
  540. for( asUINT c = 0; c < methods.GetLength(); c++ )
  541. {
  542. if( engine->scriptFunctions[methods[c]] )
  543. engine->scriptFunctions[methods[c]]->ReleaseInternal();
  544. }
  545. methods.SetLength(0);
  546. for( asUINT d = 0; d < virtualFunctionTable.GetLength(); d++ )
  547. {
  548. if( virtualFunctionTable[d] )
  549. virtualFunctionTable[d]->ReleaseInternal();
  550. }
  551. virtualFunctionTable.SetLength(0);
  552. // GC behaviours
  553. if( beh.addref )
  554. engine->scriptFunctions[beh.addref]->ReleaseInternal();
  555. beh.addref = 0;
  556. if( beh.release )
  557. engine->scriptFunctions[beh.release]->ReleaseInternal();
  558. beh.release = 0;
  559. if( beh.gcEnumReferences )
  560. engine->scriptFunctions[beh.gcEnumReferences]->ReleaseInternal();
  561. beh.gcEnumReferences = 0;
  562. if( beh.gcGetFlag )
  563. engine->scriptFunctions[beh.gcGetFlag]->ReleaseInternal();
  564. beh.gcGetFlag = 0;
  565. if( beh.gcGetRefCount )
  566. engine->scriptFunctions[beh.gcGetRefCount]->ReleaseInternal();
  567. beh.gcGetRefCount = 0;
  568. if( beh.gcReleaseAllReferences )
  569. engine->scriptFunctions[beh.gcReleaseAllReferences]->ReleaseInternal();
  570. beh.gcReleaseAllReferences = 0;
  571. if( beh.gcSetFlag )
  572. engine->scriptFunctions[beh.gcSetFlag]->ReleaseInternal();
  573. beh.gcSetFlag = 0;
  574. if ( beh.getWeakRefFlag )
  575. engine->scriptFunctions[beh.getWeakRefFlag]->ReleaseInternal();
  576. beh.getWeakRefFlag = 0;
  577. }
  578. END_AS_NAMESPACE