| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| #pragma once |
| |
| class ISourceHolder; |
| namespace Js |
| { |
| template <typename TLoadCallback, typename TUnloadCallback> |
| class JsrtSourceHolder sealed : public ISourceHolder |
| { |
| private: |
| enum MapRequestFor { Source = 1, Length = 2 }; |
| |
| FieldNoBarrier(TLoadCallback) scriptLoadCallback; |
| FieldNoBarrier(TUnloadCallback) scriptUnloadCallback; |
| Field(JsSourceContext) sourceContext; |
| |
| #ifndef NTBUILD |
| Field(JsValueRef) mappedScriptValue; |
| Field(DetachedStateBase*) mappedSerializedScriptValue; |
| #endif |
| Field(utf8char_t const *) mappedSource; |
| Field(size_t) mappedSourceByteLength; |
| Field(size_t) mappedAllocLength; |
| |
| // Wrapper methods with Asserts to ensure that we aren't trying to access unmapped source |
| utf8char_t const * GetMappedSource() |
| { |
| AssertMsg(mappedSource != nullptr, "Our mapped source is nullptr, isSourceMapped (Assert above) should be false."); |
| AssertMsg(scriptUnloadCallback != nullptr, "scriptUnloadCallback is null, this means that this object has been finalized."); |
| return mappedSource; |
| }; |
| |
| size_t GetMappedSourceLength() |
| { |
| AssertMsg(mappedSource != nullptr, "Our mapped source is nullptr, isSourceMapped (Assert above) should be false."); |
| AssertMsg(scriptUnloadCallback != nullptr, "scriptUnloadCallback is null, this means that this object has been finalized."); |
| return mappedSourceByteLength; |
| }; |
| |
| void EnsureSource(MapRequestFor requestedFor, const WCHAR* reasonString); |
| |
| public: |
| JsrtSourceHolder(_In_ TLoadCallback scriptLoadCallback, |
| _In_ TUnloadCallback scriptUnloadCallback, |
| _In_ JsSourceContext sourceContext, |
| Js::ArrayBuffer* serializedScriptValue = nullptr) : |
| scriptLoadCallback(scriptLoadCallback), |
| scriptUnloadCallback(scriptUnloadCallback), |
| sourceContext(sourceContext), |
| #ifndef NTBUILD |
| mappedScriptValue(nullptr), |
| mappedSerializedScriptValue(serializedScriptValue == nullptr ? nullptr : serializedScriptValue->DetachAndGetState(false /*queueForDelayFree*/)), |
| #endif |
| mappedSourceByteLength(0), |
| mappedSource(nullptr) |
| { |
| AssertMsg(scriptLoadCallback != nullptr, "script load callback given is null."); |
| AssertMsg(scriptUnloadCallback != nullptr, "script unload callback given is null."); |
| }; |
| |
| virtual bool IsEmpty() override |
| { |
| return false; |
| } |
| |
| // Following two methods do not attempt any source mapping |
| LPCUTF8 GetSourceUnchecked() |
| { |
| return this->GetMappedSource(); |
| } |
| |
| // Following two methods are calls to EnsureSource before attempting to get the source |
| virtual LPCUTF8 GetSource(const WCHAR* reasonString) override |
| { |
| this->EnsureSource(MapRequestFor::Source, reasonString); |
| return this->GetMappedSource(); |
| } |
| |
| virtual size_t GetByteLength(const WCHAR* reasonString) override |
| { |
| this->EnsureSource(MapRequestFor::Length, reasonString); |
| return this->GetMappedSourceLength(); |
| } |
| |
| virtual void Finalize(bool isShutdown) override; |
| |
| virtual void Dispose(bool isShutdown) override |
| { |
| #ifndef NTBUILD |
| if (this->mappedSerializedScriptValue != nullptr) |
| { |
| // We have to extend the buffer data's lifetime until Dispose because |
| // it might be used during finalization of other objects, such as |
| // FunctionEntryPointInfo which wants to log its name. |
| this->mappedSerializedScriptValue->CleanUp(); |
| } |
| #endif |
| } |
| |
| virtual void Mark(Recycler * recycler) override |
| { |
| } |
| |
| virtual void Unload() override; |
| |
| virtual bool Equals(ISourceHolder* other) override |
| { |
| return this == other || |
| (this->GetByteLength(_u("Equal Comparison")) == other->GetByteLength(_u("Equal Comparison")) |
| && (this->GetSource(_u("Equal Comparison")) == other->GetSource(_u("Equal Comparison")) |
| || memcmp(this->GetSource(_u("Equal Comparison")), other->GetSource(_u("Equal Comparison")), this->GetByteLength(_u("Equal Comparison"))) == 0)); |
| } |
| |
| virtual hash_t GetHashCode() override |
| { |
| LPCUTF8 source = GetSource(_u("Hash Code Calculation")); |
| size_t byteLength = GetByteLength(_u("Hash Code Calculation")); |
| Assert(byteLength < MAXUINT32); |
| return JsUtil::CharacterBuffer<utf8char_t>::StaticGetHashCode(source, (charcount_t)byteLength); |
| } |
| |
| |
| virtual bool IsDeferrable() override |
| { |
| return !PHASE_OFF1(Js::DeferSourceLoadPhase); |
| } |
| }; |
| } |