blob: 04d21e133d5b12c864e284b9e2b3133b8f116829 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"
#if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_PROJECTION)
#include "errstr.h"
#include "Library/EngineInterfaceObject.h"
#include "Types/DeferredTypeHandler.h"
#define IfFailThrowHr(op) \
if (FAILED(hr=(op))) \
{ \
JavascriptError::MapAndThrowError(scriptContext, hr); \
} \
#define IfFailAssertAndThrowHr(op) \
if (FAILED(hr=(op))) \
{ \
AssertMsg(false, "HRESULT was a failure."); \
JavascriptError::MapAndThrowError(scriptContext, hr); \
} \
#define SetPropertyOn(obj, propID, value) \
obj->SetProperty(propID, value, Js::PropertyOperationFlags::PropertyOperation_None, nullptr) \
#define SetStringPropertyOn(obj, propID, propValue) \
SetPropertyOn(obj, propID, Js::JavascriptString::NewCopySz(propValue, scriptContext)) \
#define SetHSTRINGPropertyOn(obj, propID, hstringValue) \
SetStringPropertyOn(obj, propID, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
#define SetPropertyLOn(obj, literalProperty, value) \
obj->SetProperty(Js::JavascriptString::NewCopySz(literalProperty, scriptContext), value, Js::PropertyOperationFlags::PropertyOperation_None, nullptr) \
#define SetStringPropertyLOn(obj, literalProperty, propValue) \
SetPropertyLOn(obj, literalProperty, Js::JavascriptString::NewCopySz(propValue, scriptContext)) \
#define SetHSTRINGPropertyLOn(obj, literalProperty, hstringValue) \
SetStringPropertyLOn(obj, literalProperty, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
#define SetPropertyBuiltInOn(obj, builtInPropID, value) \
SetPropertyOn(obj, Js::PropertyIds::builtInPropID, value) \
#define SetStringPropertyBuiltInOn(obj, builtInPropID, propValue) \
SetPropertyBuiltInOn(obj, builtInPropID, Js::JavascriptString::NewCopySz(propValue, scriptContext))
#define SetHSTRINGPropertyBuiltInOn(obj, builtInPropID, hstringValue) \
SetStringPropertyBuiltInOn(obj, builtInPropID, wgl->WindowsGetStringRawBuffer(hstringValue, &length)) \
#define GetPropertyFrom(obj, propertyID) \
Js::JavascriptOperators::GetProperty(obj, propertyID, &propertyValue, scriptContext) \
#define GetPropertyLFrom(obj, propertyName) \
GetPropertyFrom(obj, scriptContext->GetOrAddPropertyIdTracked(propertyName, wcslen(propertyName)))
#define GetPropertyBuiltInFrom(obj, builtInPropID) \
GetPropertyFrom(obj, Js::PropertyIds::builtInPropID) \
#define GetTypedPropertyBuiltInFrom(obj, builtInPropID, Type) \
(GetPropertyFrom(obj, Js::PropertyIds::builtInPropID) && Type::Is(propertyValue)) \
#define HasPropertyOn(obj, propID) \
Js::JavascriptOperators::HasProperty(obj, propID) \
#define HasPropertyBuiltInOn(obj, builtInPropID) \
HasPropertyOn(obj, Js::PropertyIds::builtInPropID) \
#define HasPropertyLOn(obj, propertyName) \
HasPropertyOn(obj, scriptContext->GetOrAddPropertyIdTracked(propertyName, wcslen(propertyName)))
namespace Js
{
EngineExtensionObjectBase* EngineInterfaceObject::GetEngineExtension(EngineInterfaceExtensionKind extensionKind) const
{
AnalysisAssert(extensionKind >= 0 && extensionKind <= MaxEngineInterfaceExtensionKind);
if (extensionKind <= MaxEngineInterfaceExtensionKind)
{
Assert(engineExtensions[extensionKind] == nullptr || engineExtensions[extensionKind]->GetExtensionKind() == extensionKind);
return engineExtensions[extensionKind];
}
return nullptr;
}
void EngineInterfaceObject::SetEngineExtension(EngineInterfaceExtensionKind extensionKind, EngineExtensionObjectBase* extensionObject)
{
AnalysisAssert(extensionKind >= 0 && extensionKind <= MaxEngineInterfaceExtensionKind);
if (extensionKind <= MaxEngineInterfaceExtensionKind)
{
Assert(engineExtensions[extensionKind] == nullptr);
engineExtensions[extensionKind] = extensionObject;
}
}
NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::GetErrorMessage(EngineInterfaceObject::Entry_GetErrorMessage);
NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::LogDebugMessage(EngineInterfaceObject::Entry_LogDebugMessage);
NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::TagPublicLibraryCode(EngineInterfaceObject::Entry_TagPublicLibraryCode);
#ifndef GlobalBuiltIn
#define GlobalBuiltIn(global, method) \
NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::Intl_BuiltIn_##global##_##method##(global##::##method##); \
#define GlobalBuiltInConstructor(global)
#define BuiltInRaiseException(exceptionType, exceptionID) \
NoProfileFunctionInfo EngineInterfaceObject::EntryInfo::Intl_BuiltIn_raise##exceptionID(EngineInterfaceObject::EntryIntl_BuiltIn_raise##exceptionID); \
#define BuiltInRaiseException1(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID)
#define BuiltInRaiseException2(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID)
#define BuiltInRaiseException3(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID##_3)
#include "EngineInterfaceObjectBuiltIns.h"
#undef BuiltInRaiseException
#undef BuiltInRaiseException1
#undef BuiltInRaiseException2
#undef BuiltInRaiseException3
#undef GlobalBuiltInConstructor
#undef GlobalBuiltIn
#endif
EngineInterfaceObject * EngineInterfaceObject::New(Recycler * recycler, DynamicType * type)
{
EngineInterfaceObject* newObject = NewObject<EngineInterfaceObject>(recycler, type);
for (uint i = 0; i <= MaxEngineInterfaceExtensionKind; i++)
{
newObject->engineExtensions[i] = nullptr;
}
return newObject;
}
bool EngineInterfaceObject::Is(Var aValue)
{
return JavascriptOperators::GetTypeId(aValue) == TypeIds_EngineInterfaceObject;
}
EngineInterfaceObject* EngineInterfaceObject::FromVar(Var aValue)
{
AssertMsg(Is(aValue), "aValue is actually an EngineInterfaceObject");
return static_cast<EngineInterfaceObject *>(RecyclableObject::FromVar(aValue));
}
void EngineInterfaceObject::Initialize()
{
Recycler* recycler = this->GetRecycler();
ScriptContext* scriptContext = this->GetScriptContext();
JavascriptLibrary* library = scriptContext->GetLibrary();
// CommonNativeInterfaces is used as a prototype for the other native interface objects
// to share the common APIs without requiring everyone to access EngineInterfaceObject.Common.
this->commonNativeInterfaces = DynamicObject::New(recycler,
DynamicType::New(scriptContext, TypeIds_Object, library->GetObjectPrototype(), nullptr,
DeferredTypeHandler<InitializeCommonNativeInterfaces>::GetDefaultInstance()));
library->AddMember(this, Js::PropertyIds::Common, this->commonNativeInterfaces);
for (uint i = 0; i <= MaxEngineInterfaceExtensionKind; i++)
{
if (engineExtensions[i] != nullptr)
{
engineExtensions[i]->Initialize();
}
}
}
void EngineInterfaceObject::InitializeCommonNativeInterfaces(DynamicObject* commonNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
{
typeHandler->Convert(commonNativeInterfaces, mode, 38);
ScriptContext* scriptContext = commonNativeInterfaces->GetScriptContext();
JavascriptLibrary* library = scriptContext->GetLibrary();
#ifndef GlobalBuiltIn
#define GlobalBuiltIn(global, method) \
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::builtIn##global##method, &EngineInterfaceObject::EntryInfo::Intl_BuiltIn_##global##_##method##, 1); \
#define GlobalBuiltInConstructor(global) SetPropertyOn(commonNativeInterfaces, Js::PropertyIds::##global##, library->Get##global##Constructor());
#define BuiltInRaiseException(exceptionType, exceptionID) \
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::raise##exceptionID, &EngineInterfaceObject::EntryInfo::Intl_BuiltIn_raise##exceptionID, 1); \
#define BuiltInRaiseException1(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID)
#define BuiltInRaiseException2(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID)
#define BuiltInRaiseException3(exceptionType, exceptionID) BuiltInRaiseException(exceptionType, exceptionID##_3)
#include "EngineInterfaceObjectBuiltIns.h"
#undef BuiltInRaiseException
#undef BuiltInRaiseException1
#undef BuiltInRaiseException2
#undef BuiltInRaiseException3
#undef GlobalBuiltIn
#undef GlobalBuiltInConstructor
#endif
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::builtInJavascriptObjectCreate, &JavascriptObject::EntryInfo::Create, 1);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::builtInJavascriptObjectPreventExtensions, &JavascriptObject::EntryInfo::PreventExtensions, 1);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::builtInJavascriptObjectGetOwnPropertyDescriptor, &JavascriptObject::EntryInfo::GetOwnPropertyDescriptor, 1);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::builtInGlobalObjectEval, &GlobalObject::EntryInfo::Eval, 2);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::getErrorMessage, &EngineInterfaceObject::EntryInfo::GetErrorMessage, 1);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::logDebugMessage, &EngineInterfaceObject::EntryInfo::LogDebugMessage, 1);
library->AddFunctionToLibraryObject(commonNativeInterfaces, Js::PropertyIds::tagPublicLibraryCode, &EngineInterfaceObject::EntryInfo::TagPublicLibraryCode, 1);
commonNativeInterfaces->SetHasNoEnumerableProperties(true);
}
Var EngineInterfaceObject::Entry_GetErrorMessage(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
if (callInfo.Count < 2)
{
return scriptContext->GetLibrary()->GetUndefined();
}
int hr = Js::JavascriptConversion::ToInt32(args[1], scriptContext);
int resourceId;
switch(hr)
{
case ASYNCERR_NoErrorInErrorState:
resourceId = 5200;
break;
case ASYNCERR_InvalidStatusArg:
resourceId = 5201;
break;
case ASYNCERR_InvalidSenderArg:
resourceId = 5202;
break;
default:
AssertMsg(false, "Invalid HRESULT passed to GetErrorMessage. This shouldn't come from Promise.js - who called us?");
return scriptContext->GetLibrary()->GetUndefined();
}
const int strLength = 1024;
OLECHAR errorString[strLength];
if(FGetResourceString(resourceId, errorString, strLength))
{
return Js::JavascriptString::NewCopySz(errorString, scriptContext);
}
AssertMsg(false, "FGetResourceString returned false.");
return scriptContext->GetLibrary()->GetUndefined();
}
Var EngineInterfaceObject::Entry_LogDebugMessage(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
#if DBG
if (callInfo.Count < 2 || !JavascriptString::Is(args.Values[1]))
{
return scriptContext->GetLibrary()->GetUndefined();
}
JavascriptString* message = JavascriptString::FromVar(args.Values[1]);
Output::Print(message->GetString());
Output::Flush();
#endif
return scriptContext->GetLibrary()->GetUndefined();
}
Var EngineInterfaceObject::Entry_TagPublicLibraryCode(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
if (callInfo.Count >= 2 && JavascriptFunction::Is(args.Values[1]))
{
JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[1]);
func->GetFunctionProxy()->SetIsPublicLibraryCode();
if (callInfo.Count >= 3 && JavascriptString::Is(args.Values[2]))
{
JavascriptString* customFunctionName = JavascriptString::FromVar(args.Values[2]);
// tagPublicFunction("Intl.Collator", Collator); in Intl.js calls TagPublicLibraryCode the expected name is Collator so we need to calculate the offset
const char16 * shortName = wcsrchr(customFunctionName->GetString(), _u('.'));
uint shortNameOffset = 0;
if (shortName != nullptr)
{
// JavascriptString length is bounded by uint max
shortName++;
shortNameOffset = static_cast<uint>(shortName - customFunctionName->GetString());
}
func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(customFunctionName->GetString(), customFunctionName->GetLength(), shortNameOffset);
}
return func;
}
return scriptContext->GetLibrary()->GetUndefined();
}
#ifndef GlobalBuiltIn
#define GlobalBuiltIn(global, method)
#define GlobalBuiltInConstructor(global)
#define BuiltInRaiseException(exceptionType, exceptionID) \
Var EngineInterfaceObject::EntryIntl_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
{ \
EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
\
JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
}
#define BuiltInRaiseException1(exceptionType, exceptionID) \
Var EngineInterfaceObject::EntryIntl_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
{ \
EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
\
if(args.Info.Count < 2 || !JavascriptString::Is(args.Values[1])) \
{ \
Assert(false); \
JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
} \
JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, JavascriptString::FromVar(args.Values[1])->GetSz()); \
}
#define BuiltInRaiseException2(exceptionType, exceptionID) \
Var EngineInterfaceObject::EntryIntl_BuiltIn_raise##exceptionID(RecyclableObject *function, CallInfo callInfo, ...) \
{ \
EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
\
if(args.Info.Count < 3 || !JavascriptString::Is(args.Values[1]) || !JavascriptString::Is(args.Values[2])) \
{ \
Assert(false); \
JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
} \
JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, JavascriptString::FromVar(args.Values[1])->GetSz(), JavascriptString::FromVar(args.Values[2])->GetSz()); \
}
#define BuiltInRaiseException3(exceptionType, exceptionID) \
Var EngineInterfaceObject::EntryIntl_BuiltIn_raise##exceptionID##_3(RecyclableObject *function, CallInfo callInfo, ...) \
{ \
EngineInterfaceObject_CommonFunctionProlog(function, callInfo); \
\
if(args.Info.Count < 4 || !JavascriptString::Is(args.Values[1]) || !JavascriptString::Is(args.Values[2]) || !JavascriptString::Is(args.Values[3])) \
{ \
Assert(false); \
JavascriptError::Throw##exceptionType(scriptContext, JSERR_##exceptionID); \
} \
JavascriptError::Throw##exceptionType##Var(scriptContext, JSERR_##exceptionID, JavascriptString::FromVar(args.Values[1])->GetSz(), JavascriptString::FromVar(args.Values[2])->GetSz(), JavascriptString::FromVar(args.Values[3])->GetSz()); \
}
#include "EngineInterfaceObjectBuiltIns.h"
#undef BuiltInRaiseException
#undef BuiltInRaiseException1
#undef BuiltInRaiseException2
#undef BuiltInRaiseException3
#undef GlobalBuiltIn
#undef GlobalBuiltInConstructor
#endif
}
#endif // ENABLE_INTL_OBJECT || ENABLE_PROJECTION