ModuleRoot.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLibraryPch.h"
  6. namespace Js
  7. {
  8. ModuleRoot::ModuleRoot(DynamicType * type):
  9. RootObjectBase(type)
  10. {
  11. }
  12. void ModuleRoot::SetHostObject(ModuleID moduleID, HostObjectBase * hostObject)
  13. {
  14. this->moduleID = moduleID;
  15. __super::SetHostObject(hostObject);
  16. }
  17. BOOL ModuleRoot::HasProperty(PropertyId propertyId)
  18. {
  19. if (DynamicObject::HasProperty(propertyId))
  20. {
  21. return TRUE;
  22. }
  23. else if (this->hostObject && JavascriptOperators::HasProperty(this->hostObject, propertyId))
  24. {
  25. return TRUE;
  26. }
  27. return this->GetLibrary()->GetGlobalObject()->GlobalObject::HasProperty(propertyId);
  28. }
  29. BOOL ModuleRoot::EnsureProperty(PropertyId propertyId)
  30. {
  31. if (!RootObjectBase::HasOwnPropertyCheckNoRedecl(propertyId))
  32. {
  33. // Cannot pass the extra PropertyOperation_PreInit flag, because module root uses SetSlot directly from
  34. // SetRootProperty. If the property is not yet initialized SetSlot will (correctly) assert.
  35. this->InitProperty(propertyId, this->GetLibrary()->GetUndefined(), (PropertyOperationFlags)(PropertyOperation_SpecialValue | PropertyOperation_NonFixedValue));
  36. }
  37. return true;
  38. }
  39. BOOL ModuleRoot::HasRootProperty(PropertyId propertyId)
  40. {
  41. if (__super::HasRootProperty(propertyId))
  42. {
  43. return TRUE;
  44. }
  45. else if (this->hostObject && JavascriptOperators::HasProperty(this->hostObject, propertyId))
  46. {
  47. return TRUE;
  48. }
  49. return this->GetLibrary()->GetGlobalObject()->GlobalObject::HasRootProperty(propertyId);
  50. }
  51. BOOL ModuleRoot::HasOwnProperty(PropertyId propertyId)
  52. {
  53. return DynamicObject::HasProperty(propertyId);
  54. }
  55. BOOL ModuleRoot::GetProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
  56. {
  57. PropertyIndex index = GetPropertyIndex(propertyId);
  58. if (index != Constants::NoSlot)
  59. {
  60. *value = this->GetSlot(index);
  61. if (info) // Avoid testing IsWritable if info not being queried
  62. {
  63. PropertyValueInfo::Set(info, this, index, IsWritable(propertyId) ? PropertyWritable : PropertyNone);
  64. if (this->IsFixedProperty(propertyId))
  65. {
  66. PropertyValueInfo::DisableStoreFieldCache(info);
  67. }
  68. }
  69. return TRUE;
  70. }
  71. if (this->hostObject && JavascriptOperators::GetProperty(this->hostObject, propertyId, value, requestContext))
  72. {
  73. return TRUE;
  74. }
  75. //
  76. // Try checking the global object
  77. // if the module root doesn't have the property and the host object also doesn't have it
  78. //
  79. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  80. return globalObj->GlobalObject::GetProperty(originalInstance, propertyId, value, NULL, requestContext);
  81. }
  82. BOOL ModuleRoot::GetRootProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
  83. {
  84. PropertyIndex index = GetRootPropertyIndex(propertyId);
  85. if (index != Constants::NoSlot)
  86. {
  87. *value = this->GetSlot(index);
  88. if (info) // Avoid testing IsWritable if info not being queried
  89. {
  90. PropertyValueInfo::Set(info, this, index, IsWritable(propertyId) ? PropertyWritable : PropertyNone);
  91. if (this->IsFixedProperty(propertyId))
  92. {
  93. PropertyValueInfo::DisableStoreFieldCache(info);
  94. }
  95. }
  96. return TRUE;
  97. }
  98. if (this->hostObject && JavascriptOperators::GetProperty(this->hostObject, propertyId, value, requestContext))
  99. {
  100. return TRUE;
  101. }
  102. //
  103. // Try checking the global object
  104. // if the module root doesn't have the property and the host object also doesn't have it
  105. //
  106. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  107. return globalObj->GlobalObject::GetRootProperty(originalInstance, propertyId, value, NULL, requestContext);
  108. }
  109. BOOL ModuleRoot::GetProperty(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext)
  110. {
  111. PropertyRecord const * propertyRecord;
  112. this->GetScriptContext()->GetOrAddPropertyRecord(propertyNameString->GetString(), propertyNameString->GetLength(), &propertyRecord);
  113. return ModuleRoot::GetProperty(originalInstance, propertyRecord->GetPropertyId(), value, info, requestContext);
  114. }
  115. BOOL ModuleRoot::GetAccessors(PropertyId propertyId, Var* getter, Var* setter, ScriptContext * requestContext)
  116. {
  117. if (DynamicObject::GetAccessors(propertyId, getter, setter, requestContext))
  118. {
  119. return TRUE;
  120. }
  121. if (this->hostObject)
  122. {
  123. return this->hostObject->GetAccessors(propertyId, getter, setter, requestContext);
  124. }
  125. // Try checking the global object
  126. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  127. return globalObj->GlobalObject::GetAccessors(propertyId, getter, setter, requestContext);
  128. }
  129. BOOL ModuleRoot::GetPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info,
  130. ScriptContext* requestContext)
  131. {
  132. PropertyIndex index = GetPropertyIndex(propertyId);
  133. if (index != Constants::NoSlot)
  134. {
  135. *value = this->GetSlot(index);
  136. if (info) // Avoid testing IsWritable if info not being queried
  137. {
  138. PropertyValueInfo::Set(info, this, index, IsWritable(propertyId) ? PropertyWritable : PropertyNone);
  139. if (this->IsFixedProperty(propertyId))
  140. {
  141. PropertyValueInfo::DisableStoreFieldCache(info);
  142. }
  143. }
  144. return TRUE;
  145. }
  146. if (this->hostObject && JavascriptOperators::GetPropertyReference(this->hostObject, propertyId, value, requestContext))
  147. {
  148. return TRUE;
  149. }
  150. //
  151. // Try checking the global object
  152. // if the module root doesn't have the property and the host object also doesn't have it
  153. //
  154. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  155. return globalObj->GlobalObject::GetPropertyReference(originalInstance, propertyId, value, NULL, requestContext);
  156. }
  157. BOOL ModuleRoot::GetRootPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info,
  158. ScriptContext* requestContext)
  159. {
  160. PropertyIndex index = GetRootPropertyIndex(propertyId);
  161. if (index != Constants::NoSlot)
  162. {
  163. *value = this->GetSlot(index);
  164. if (info) // Avoid testing IsWritable if info not being queried
  165. {
  166. PropertyValueInfo::Set(info, this, index, IsWritable(propertyId) ? PropertyWritable : PropertyNone);
  167. if (this->IsFixedProperty(propertyId))
  168. {
  169. PropertyValueInfo::DisableStoreFieldCache(info);
  170. }
  171. }
  172. return TRUE;
  173. }
  174. if (this->hostObject && JavascriptOperators::GetPropertyReference(this->hostObject, propertyId, value, requestContext))
  175. {
  176. return TRUE;
  177. }
  178. //
  179. // Try checking the global object
  180. // if the module root doesn't have the property and the host object also doesn't have it
  181. //
  182. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  183. return globalObj->GlobalObject::GetRootPropertyReference(originalInstance, propertyId, value, NULL, requestContext);
  184. }
  185. BOOL ModuleRoot::SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
  186. {
  187. PropertyIndex index = GetPropertyIndex(propertyId);
  188. if (index != Constants::NoSlot)
  189. {
  190. if (this->IsWritable(propertyId) == FALSE)
  191. {
  192. JavascriptError::ThrowCantAssignIfStrictMode(flags, this->GetScriptContext());
  193. if (!this->IsFixedProperty(propertyId))
  194. {
  195. PropertyValueInfo::Set(info, this, index, PropertyNone); // Try to cache property info even if not writable
  196. }
  197. else
  198. {
  199. PropertyValueInfo::SetNoCache(info, this);
  200. }
  201. return FALSE;
  202. }
  203. this->SetSlot(SetSlotArguments(propertyId, index, value));
  204. if (!this->IsFixedProperty(propertyId))
  205. {
  206. PropertyValueInfo::Set(info, this, index);
  207. }
  208. else
  209. {
  210. PropertyValueInfo::SetNoCache(info, this);
  211. }
  212. return TRUE;
  213. }
  214. else if (this->hostObject && this->hostObject->HasProperty(propertyId))
  215. {
  216. return this->hostObject->SetProperty(propertyId, value, flags, NULL);
  217. }
  218. //
  219. // Try checking the global object
  220. // if the module root doesn't have the property and the host object also doesn't have it
  221. //
  222. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  223. BOOL setAttempted = TRUE;
  224. if (globalObj->SetExistingProperty(propertyId, value, NULL, &setAttempted))
  225. {
  226. return TRUE;
  227. }
  228. //
  229. // Set was attempted. But the set operation returned false.
  230. // This happens, when the property is read only.
  231. // In those scenarios, we should be setting the property with default attributes
  232. //
  233. if (setAttempted)
  234. {
  235. return FALSE;
  236. }
  237. return DynamicObject::SetProperty(propertyId, value, flags, info);
  238. }
  239. BOOL ModuleRoot::SetRootProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
  240. {
  241. PropertyIndex index = GetRootPropertyIndex(propertyId);
  242. if (index != Constants::NoSlot)
  243. {
  244. if (this->IsWritable(propertyId) == FALSE)
  245. {
  246. JavascriptError::ThrowCantAssignIfStrictMode(flags, this->GetScriptContext());
  247. if (!this->IsFixedProperty(propertyId))
  248. {
  249. PropertyValueInfo::Set(info, this, index, PropertyNone); // Try to cache property info even if not writable
  250. }
  251. else
  252. {
  253. PropertyValueInfo::SetNoCache(info, this);
  254. }
  255. return FALSE;
  256. }
  257. this->SetSlot(SetSlotArgumentsRoot(propertyId, true, index, value));
  258. if (!this->IsFixedProperty(propertyId))
  259. {
  260. PropertyValueInfo::Set(info, this, index);
  261. }
  262. else
  263. {
  264. PropertyValueInfo::SetNoCache(info, this);
  265. }
  266. return TRUE;
  267. }
  268. else if (this->hostObject && this->hostObject->HasProperty(propertyId))
  269. {
  270. return this->hostObject->SetProperty(propertyId, value, flags, NULL);
  271. }
  272. //
  273. // Try checking the global object
  274. // if the module root doesn't have the property and the host object also doesn't have it
  275. //
  276. GlobalObject* globalObj = this->GetLibrary()->GetGlobalObject();
  277. BOOL setAttempted = TRUE;
  278. if (globalObj->SetExistingRootProperty(propertyId, value, NULL, &setAttempted))
  279. {
  280. return TRUE;
  281. }
  282. //
  283. // Set was attempted. But the set operation returned false.
  284. // This happens, when the property is read only.
  285. // In those scenarios, we should be setting the property with default attributes
  286. //
  287. if (setAttempted)
  288. {
  289. return FALSE;
  290. }
  291. return __super::SetRootProperty(propertyId, value, (PropertyOperationFlags)(flags | PropertyOperation_NonFixedValue), info);
  292. }
  293. BOOL ModuleRoot::SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info)
  294. {
  295. PropertyRecord const * propertyRecord;
  296. this->GetScriptContext()->GetOrAddPropertyRecord(propertyNameString->GetString(), propertyNameString->GetLength(), &propertyRecord);
  297. return ModuleRoot::SetProperty(propertyRecord->GetPropertyId(), value, (PropertyOperationFlags)(flags | PropertyOperation_NonFixedValue), info);
  298. }
  299. BOOL ModuleRoot::InitPropertyScoped(PropertyId propertyId, Var value)
  300. {
  301. return DynamicObject::InitProperty(propertyId, value, PropertyOperation_NonFixedValue);
  302. }
  303. BOOL ModuleRoot::InitFuncScoped(PropertyId propertyId, Var value)
  304. {
  305. // Var binding of functions declared in eval are elided when conflicting
  306. // with global scope let/const variables, so do not actually set the
  307. // property if it exists and is a let/const variable.
  308. bool noRedecl = false;
  309. if (!GetTypeHandler()->HasRootProperty(this, propertyId, &noRedecl) || !noRedecl)
  310. {
  311. DynamicObject::InitProperty(propertyId, value, PropertyOperation_NonFixedValue);
  312. }
  313. return true;
  314. }
  315. BOOL ModuleRoot::SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags)
  316. {
  317. if (DynamicObject::SetAccessors(propertyId, getter, setter, flags))
  318. {
  319. return TRUE;
  320. }
  321. if (this->hostObject)
  322. {
  323. return this->hostObject->SetAccessors(propertyId, getter, setter, flags);
  324. }
  325. //
  326. // Try checking the global object
  327. // if the module root doesn't have the property and the host object also doesn't have it
  328. //
  329. GlobalObject* globalObj = GetScriptContext()->GetGlobalObject();
  330. return globalObj->GlobalObject::SetAccessors(propertyId, getter, setter, flags);
  331. }
  332. BOOL ModuleRoot::DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags)
  333. {
  334. int index = GetPropertyIndex(propertyId);
  335. if (index != Constants::NoSlot)
  336. {
  337. return FALSE;
  338. }
  339. else if (this->hostObject && this->hostObject->HasProperty(propertyId))
  340. {
  341. return this->hostObject->DeleteProperty(propertyId, flags);
  342. }
  343. return this->GetLibrary()->GetGlobalObject()->GlobalObject::DeleteProperty(propertyId, flags);
  344. }
  345. BOOL ModuleRoot::DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags)
  346. {
  347. PropertyRecord const *propertyRecord = nullptr;
  348. if (JavascriptOperators::ShouldTryDeleteProperty(this, propertyNameString, &propertyRecord))
  349. {
  350. Assert(propertyRecord);
  351. return DeleteProperty(propertyRecord->GetPropertyId(), flags);
  352. }
  353. return TRUE;
  354. }
  355. BOOL ModuleRoot::DeleteRootProperty(PropertyId propertyId, PropertyOperationFlags flags)
  356. {
  357. int index = GetRootPropertyIndex(propertyId);
  358. if (index != Constants::NoSlot)
  359. {
  360. return FALSE;
  361. }
  362. else if (this->hostObject && this->hostObject->HasProperty(propertyId))
  363. {
  364. return this->hostObject->DeleteProperty(propertyId, flags);
  365. }
  366. return this->GetLibrary()->GetGlobalObject()->GlobalObject::DeleteRootProperty(propertyId, flags);
  367. }
  368. BOOL ModuleRoot::HasItem(uint32 index)
  369. {
  370. return DynamicObject::HasItem(index)
  371. || (this->hostObject && JavascriptOperators::HasItem(this->hostObject, index));
  372. }
  373. BOOL ModuleRoot::HasOwnItem(uint32 index)
  374. {
  375. return DynamicObject::HasItem(index);
  376. }
  377. BOOL ModuleRoot::GetItemReference(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext)
  378. {
  379. if (DynamicObject::GetItemReference(originalInstance, index, value, requestContext))
  380. {
  381. return TRUE;
  382. }
  383. if (this->hostObject && this->hostObject->GetItemReference(originalInstance, index, value, requestContext))
  384. {
  385. return TRUE;
  386. }
  387. *value = requestContext->GetMissingItemResult();
  388. return FALSE;
  389. }
  390. BOOL ModuleRoot::SetItem(uint32 index, Var value, PropertyOperationFlags flags)
  391. {
  392. if (DynamicObject::SetItem(index, value, flags))
  393. {
  394. return TRUE;
  395. }
  396. if (this->hostObject)
  397. {
  398. return this->hostObject->SetItem(index, value, flags);
  399. }
  400. return FALSE;
  401. }
  402. BOOL ModuleRoot::GetItem(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext)
  403. {
  404. if (DynamicObject::GetItem(originalInstance, index, value, requestContext))
  405. {
  406. return TRUE;
  407. }
  408. if (this->hostObject && this->hostObject->GetItem(originalInstance, index, value, requestContext))
  409. {
  410. return TRUE;
  411. }
  412. *value = requestContext->GetMissingItemResult();
  413. return FALSE;
  414. }
  415. BOOL ModuleRoot::GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
  416. {
  417. stringBuilder->AppendCppLiteral(_u("{Named Item}"));
  418. return TRUE;
  419. }
  420. BOOL ModuleRoot::GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
  421. {
  422. stringBuilder->AppendCppLiteral(_u("Object, (Named Item)"));
  423. return TRUE;
  424. }
  425. }