diff --git a/deps/chakrashim/core/Build/Chakra.Build.props b/deps/chakrashim/core/Build/Chakra.Build.props
index 8c3424e8ae9..a046be9f23b 100644
--- a/deps/chakrashim/core/Build/Chakra.Build.props
+++ b/deps/chakrashim/core/Build/Chakra.Build.props
@@ -30,6 +30,14 @@
%(PreprocessorDefinitions);
DISABLE_JIT=1
+
+ %(PreprocessorDefinitions);
+ BUILD_WITHOUT_SCRIPT_DEBUG=1
+
+
+ %(PreprocessorDefinitions);
+ CHAKRACORE_LITE
+
%(PreprocessorDefinitions);
INTL_ICU=1
@@ -39,11 +47,12 @@
GLOBAL_ENABLE_WRITE_BARRIER=1
%(PreprocessorDefinitions);NTDDI_VERSION=$(NTDDIVersion)
-
+
%(DisableSpecificWarnings);
4458;
4312;
+ 4800;
MultiThreadedDebugDLL
diff --git a/deps/chakrashim/core/Build/Chakra.Core.sln b/deps/chakrashim/core/Build/Chakra.Core.sln
index 96acd4a049f..90d117baae8 100644
--- a/deps/chakrashim/core/Build/Chakra.Core.sln
+++ b/deps/chakrashim/core/Build/Chakra.Core.sln
@@ -2,7 +2,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
-MinimumVisualStudioVersion = 10.0.40219.1
+MinimumVisualStudioVersion = 14.0.00000.0
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChakraCore", "..\bin\ChakraCore\ChakraCore.vcxproj", "{EA882C8D-81FC-42FE-ABD5-2666DB933FDB}"
ProjectSection(ProjectDependencies) = postProject
{1876E800-AD77-48C4-A2F7-E5265F24AC38} = {1876E800-AD77-48C4-A2F7-E5265F24AC38}
@@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChakraCore", "..\bin\Chakra
{2F6A1847-BFAF-4B8A-9463-AC39FB46B96A} = {2F6A1847-BFAF-4B8A-9463-AC39FB46B96A}
{6979EC58-7A28-465C-A694-F3323A1F5401} = {6979EC58-7A28-465C-A694-F3323A1F5401}
{F6FAD160-5A4B-476A-93AC-33E0B3A18C0C} = {F6FAD160-5A4B-476A-93AC-33E0B3A18C0C}
+ {F48B3491-81DF-4F49-B35F-3308CBE6A379} = {F48B3491-81DF-4F49-B35F-3308CBE6A379}
{18CF279F-188D-4655-B03D-74F65388E7D1} = {18CF279F-188D-4655-B03D-74F65388E7D1}
{ABC904AD-9415-46F8-AA23-E33193F81F7C} = {ABC904AD-9415-46F8-AA23-E33193F81F7C}
{8C61E4E7-F0D6-420D-A352-3E6E50D406DD} = {8C61E4E7-F0D6-420D-A352-3E6E50D406DD}
@@ -755,4 +756,7 @@ Global
{02D4FD92-AD34-40CA-85DF-4D6C7E3A1F22} = {546172B2-F084-4363-BE35-06010663D319}
{F48B3491-81DF-4F49-B35F-3308CBE6A379} = {D8216B93-BD6E-4293-8D98-79CEF7CF66BC}
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1F6CA1BC-6C01-4C82-8505-6A7690EBD556}
+ EndGlobalSection
EndGlobal
diff --git a/deps/chakrashim/core/Build/Common.Build.Default.props b/deps/chakrashim/core/Build/Common.Build.Default.props
index 4f192e30777..da159f3f525 100644
--- a/deps/chakrashim/core/Build/Common.Build.Default.props
+++ b/deps/chakrashim/core/Build/Common.Build.Default.props
@@ -28,6 +28,11 @@
+
+
+ false
+ false
+
@@ -62,7 +67,9 @@
$(OutBaseDir)\$(SolutionName)
$(SolutionDir)VcBuild
$(OutBaseDir).$(Clang)
- $(OutBaseDir).NoJIT
+ $(OutBaseDir).Lite
+ $(OutBaseDir).NoJIT
+ $(OutBaseDir).NoScriptDebug
$(OutBaseDir).SWB
$(OutBaseDir)
diff --git a/deps/chakrashim/core/Build/Common.Build.ProjectConfiguration.props b/deps/chakrashim/core/Build/Common.Build.ProjectConfiguration.props
index 64860f5fadc..27939d2b153 100644
--- a/deps/chakrashim/core/Build/Common.Build.ProjectConfiguration.props
+++ b/deps/chakrashim/core/Build/Common.Build.ProjectConfiguration.props
@@ -42,6 +42,20 @@
ARM
+
+
+ Debug
+ ARM64
+
+
+ Test
+ ARM64
+
+
+ Release
+ ARM64
+
+
Debug
diff --git a/deps/chakrashim/core/Build/Common.Build.props b/deps/chakrashim/core/Build/Common.Build.props
index cc965c845bf..7f3334e65ac 100644
--- a/deps/chakrashim/core/Build/Common.Build.props
+++ b/deps/chakrashim/core/Build/Common.Build.props
@@ -81,7 +81,7 @@
$(IntDir)$(TargetName).pdb
$(IntDir)
-
+
%(PreprocessorDefinitions);
BYTECODE_TESTING=1
@@ -113,7 +113,7 @@
%(AdditionalOptions) /release
%(AdditionalOptions) /ignore:4221
-
+
%(AdditionalOptions) /DEBUGTYPE:CV,FIXUP
diff --git a/deps/chakrashim/core/Build/NuGet/.pack-version b/deps/chakrashim/core/Build/NuGet/.pack-version
index de28578affc..f8e233b2733 100644
--- a/deps/chakrashim/core/Build/NuGet/.pack-version
+++ b/deps/chakrashim/core/Build/NuGet/.pack-version
@@ -1 +1 @@
-1.7.6
+1.9.0
diff --git a/deps/chakrashim/core/Build/scripts/finalize_build.ps1 b/deps/chakrashim/core/Build/scripts/finalize_build.ps1
index 6ca425bd39d..cfa0c7ccbd0 100644
--- a/deps/chakrashim/core/Build/scripts/finalize_build.ps1
+++ b/deps/chakrashim/core/Build/scripts/finalize_build.ps1
@@ -10,7 +10,7 @@
param (
[Parameter(Mandatory=$True)]
- [ValidateSet("x86", "x64", "arm")]
+ [ValidateSet("x86", "x64", "arm", "arm64")]
[string]$arch,
[Parameter(Mandatory=$True)]
diff --git a/deps/chakrashim/core/Build/scripts/init_build.ps1 b/deps/chakrashim/core/Build/scripts/init_build.ps1
index ad2214c5953..c6904c2ee1d 100644
--- a/deps/chakrashim/core/Build/scripts/init_build.ps1
+++ b/deps/chakrashim/core/Build/scripts/init_build.ps1
@@ -12,7 +12,7 @@
# before running the Pre-Build script.
param (
- [ValidateSet("x86", "x64", "arm", "")]
+ [ValidateSet("x86", "x64", "arm", "arm64", "")]
[string]$arch = "",
[ValidateSet("debug", "release", "test", "codecoverage", "")]
[string]$flavor = "",
@@ -178,6 +178,7 @@ New-Item -ItemType Directory -Force -Path (Join-Path $SourcesDirectory "test\log
New-Item -ItemType Directory -Force -Path (Join-Path $BinariesDirectory "buildlogs")
New-Item -ItemType Directory -Force -Path (Join-Path $BinariesDirectory "logs")
+New-Item -ItemType Directory -Force -Path (Join-Path $DropPath "bin")
$FlavorBuildIncompleteFile = Join-Path $DropPath "${BuildType}.incomplete"
if (-not (Test-Path $FlavorBuildIncompleteFile)) {
diff --git a/deps/chakrashim/core/Build/scripts/post_build.ps1 b/deps/chakrashim/core/Build/scripts/post_build.ps1
index d04317e3b70..cb82cdbdbb5 100644
--- a/deps/chakrashim/core/Build/scripts/post_build.ps1
+++ b/deps/chakrashim/core/Build/scripts/post_build.ps1
@@ -13,7 +13,7 @@
# Finalize Build Script, which should be invoked at the very end of the build.
param (
- [ValidateSet("x86", "x64", "arm", "*")]
+ [ValidateSet("x86", "x64", "arm", "arm64", "*")]
[string]$arch = "*",
[ValidateSet("debug", "release", "test", "codecoverage", "*")]
@@ -59,7 +59,7 @@ $global:exitcode = 0
if ($arch -eq "*") {
- foreach ($arch in ("x86", "x64", "arm")) {
+ foreach ($arch in ("x86", "x64", "arm", "arm64")) {
ExecuteCommand "$PSScriptRoot\post_build.ps1 -arch $arch -flavor $flavor -srcpath ""$srcpath"" -buildRoot ""$buildRoot"" -objpath ""$objpath"" -srcsrvcmdpath ""$srcsrvcmdpath"" -bvtcmdpath ""$bvtcmdpath"" -repo ""$repo""" -logFile ""$logFile""
}
diff --git a/deps/chakrashim/core/Build/scripts/pre_build.ps1 b/deps/chakrashim/core/Build/scripts/pre_build.ps1
index 4b3402e5852..4e847732c77 100644
--- a/deps/chakrashim/core/Build/scripts/pre_build.ps1
+++ b/deps/chakrashim/core/Build/scripts/pre_build.ps1
@@ -27,7 +27,7 @@
param (
[Parameter(Mandatory=$True)]
- [ValidateSet("x86", "x64", "arm")]
+ [ValidateSet("x86", "x64", "arm", "arm64")]
[string]$arch,
[Parameter(Mandatory=$True)]
[ValidateSet("debug", "release", "test", "codecoverage")]
diff --git a/deps/chakrashim/core/Build/scripts/run_build.ps1 b/deps/chakrashim/core/Build/scripts/run_build.ps1
index d7d8b5e09fd..a0442f275c9 100644
--- a/deps/chakrashim/core/Build/scripts/run_build.ps1
+++ b/deps/chakrashim/core/Build/scripts/run_build.ps1
@@ -6,10 +6,10 @@
# Use this script to run a build for the given BuildType (arch, flavor, subtype)
param (
- [ValidateSet("x86", "x64", "arm")]
+ [ValidateSet("x86", "x64", "arm", "arm64")]
[Parameter(Mandatory=$True)]
[string]$arch,
- # We do not use ValidateSet here because this $flavor param is used to name the BuildConfuration
+ # We do not use ValidateSet here because this $flavor param is used to name the BuildConfiguration
# from the solution file. MsBuild will determine whether it is valid.
[Parameter(Mandatory=$True)]
[string]$flavor,
diff --git a/deps/chakrashim/core/CMakeLists.txt b/deps/chakrashim/core/CMakeLists.txt
index 28f45f79667..a400fe5cc32 100644
--- a/deps/chakrashim/core/CMakeLists.txt
+++ b/deps/chakrashim/core/CMakeLists.txt
@@ -126,17 +126,17 @@ function(clr_unknown_arch)
message(FATAL_ERROR "Only AMD64, ARM and I386 are supported")
endfunction()
-if(INTL_ICU_SH)
- unset(INTL_ICU_SH CACHE) # don't cache
- add_definitions(-DINTL_ICU=1)
- set(ICU_INTL_ENABLED 1)
+if(NOINTL_ICU_SH)
+ unset(NOINTL_ICU_SH CACHE) # don't cache
+ set(ICU_INTL_DISABLED 1)
endif()
if(ICU_INCLUDE_PATH)
add_definitions(-DHAS_REAL_ICU=1)
set(ICU_CC_PATH "${ICU_INCLUDE_PATH}/../lib/")
find_library(ICUUC icuuc PATHS ${ICU_CC_PATH} NO_DEFAULT_PATH)
- if(ICU_INTL_ENABLED)
+ if(NOT ICU_INTL_DISABLED)
+ add_definitions(-DINTL_ICU=1)
find_library(ICU18 icui18n PATHS ${ICU_CC_PATH} NO_DEFAULT_PATH)
# icu header files are either located under the same folder or i18n is under a relative path
# TODO (unlikely): shall we add `--icu-intl` to build.sh ?
@@ -150,22 +150,17 @@ if(ICU_INCLUDE_PATH)
if (NOT ICUDATA)
set(ICUDATA "")
endif()
- find_library(ICUTOOLS icutools PATHS ${ICU_CC_PATH} NO_DEFAULT_PATH)
- if (NOT ICUTOOLS)
- set(ICUTOOLS "")
- endif()
set(ICULIB
${ICUUC}
${ICU18}
${ICUDATA}
- ${ICUTOOLS}
)
endif()
endif()
set(CLR_CMAKE_PLATFORM_XPLAT 1)
if(CC_TARGETS_AMD64)
- add_definitions(-D_M_X64_OR_ARM64)
+ add_definitions(-DTARGET_64)
add_compile_options(-msse4.2)
if(NOT CMAKE_BUILD_TYPE STREQUAL Release)
@@ -173,7 +168,7 @@ if(CC_TARGETS_AMD64)
endif()
elseif(CC_TARGETS_X86)
add_definitions(-D__i686__)
- add_definitions(-D_M_IX86_OR_ARM32)
+ add_definitions(-DTARGET_32)
add_compile_options(-arch i386)
add_compile_options(-msse3)
@@ -182,7 +177,7 @@ elseif(CC_TARGETS_X86)
)
elseif(CC_TARGETS_ARM)
add_definitions(-D__arm__)
- add_definitions(-D_M_IX86_OR_ARM32)
+ add_definitions(-DTARGET_32)
add_definitions(-D_M_ARM32_OR_ARM64)
if(CC_TARGET_OS_OSX)
add_compile_options(-arch arm)
@@ -203,7 +198,8 @@ if(CC_TARGET_OS_LINUX OR CC_TARGET_OS_ANDROID)
if(NOT NO_ICU_PATH_GIVEN)
if(NOT CC_EMBED_ICU)
set(ICULIB "icuuc")
- if(ICU_INTL_ENABLED)
+ if(NOT ICU_INTL_DISABLED)
+ add_definitions(-DINTL_ICU=1)
set(ICULIB
"${ICULIB}"
"icui18n")
@@ -346,9 +342,18 @@ if(CLR_CMAKE_PLATFORM_XPLAT)
add_compile_options(
-fasm-blocks
-fms-extensions
- -fwrapv # Treat signed integer overflow as two's complement
+ -fwrapv # Treat signed integer overflow as two's complement
)
+ # Only disable RTTI in release builds so that TrackAlloc works for debug and test builds
+ # Also disable RTTI when building a shared library
+ # TODO: why does the shared library break with rtti disabled?
+ if(CMAKE_BUILD_TYPE STREQUAL Release)
+ if(STATIC_LIBRARY OR ICU_INTL_DISABLED)
+ add_compile_options(-fno-rtti)
+ endif()
+ endif()
+
# Clang -fsanitize.
if (CLANG_SANITIZE_SH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${CLANG_SANITIZE_SH}")
@@ -486,5 +491,21 @@ add_definitions(
-DNO_PAL_MINMAX
-DPAL_STDCPP_COMPAT
)
+
+if (ENABLE_JS_LTTNG_SH)
+ unset(ENABLE_JS_LTTNG_SH CACHE)
+ include_directories (
+ ${CMAKE_CURRENT_SOURCE_DIR}/out/lttng
+ )
+ add_subdirectory ($ENV{TARGET_PATH}/lttng ${CMAKE_CURRENT_BINARY_DIR}/lttng)
+
+ add_definitions(
+ -DENABLE_JS_ETW
+ -DENABLE_JS_LTTNG
+ )
+ set(USE_LTTNG "1")
+endif()
+
add_subdirectory (lib)
+
add_subdirectory (bin)
diff --git a/deps/chakrashim/core/CONTRIBUTING.md b/deps/chakrashim/core/CONTRIBUTING.md
index e08dc86f1ca..a12f80b8f7f 100644
--- a/deps/chakrashim/core/CONTRIBUTING.md
+++ b/deps/chakrashim/core/CONTRIBUTING.md
@@ -58,8 +58,8 @@ Changes that make it into our ChakraCore GitHub master branch have a short journ
## Issue Labels
- - [`Accepting PRs`](https://github.com/Microsoft/ChakraCore/labels/Accepting%20PRs): these issues are specifically well suited for outside contributors.
- - [`Your first PR`](https://github.com/Microsoft/ChakraCore/labels/Your%20first%20PR): these issues are small and appropriate for people who wish to familiarize themselves with GitHub pull requests and/or ChakraCore's contributor guidelines, build process, and running tests. We're here to help you get started in open source.
+ - [`help wanted`](https://github.com/Microsoft/ChakraCore/labels/help%20wanted): these issues are specifically well suited for outside contributors.
+ - [`good first issue`](https://github.com/Microsoft/ChakraCore/labels/good%20first%20issue): these issues are small and appropriate for people who wish to familiarize themselves with GitHub pull requests and/or ChakraCore's contributor guidelines, build process, and running tests. We're here to help you get started in open source.
You are welcome to work on issues that are not tagged with these labels. However, issues without these labels are often deeply involved with the requirements of the various components of ChakraCore. Therefore, please be sure to touch base with a maintainer via comments on the issue before attempting to solve it.
diff --git a/deps/chakrashim/core/LICENSE.txt b/deps/chakrashim/core/LICENSE.txt
index a6d7082e364..d5ced9877c2 100644
--- a/deps/chakrashim/core/LICENSE.txt
+++ b/deps/chakrashim/core/LICENSE.txt
@@ -1,4 +1,3 @@
-ChakraCore
The MIT License (MIT)
Copyright (c) Microsoft Corporation
diff --git a/deps/chakrashim/core/README.md b/deps/chakrashim/core/README.md
index 5fa8ffcbc01..4bd2a370869 100644
--- a/deps/chakrashim/core/README.md
+++ b/deps/chakrashim/core/README.md
@@ -94,7 +94,7 @@ If you believe you have found a security issue in ChakraCore, please share it wi
## [Building ChakraCore](https://github.com/Microsoft/ChakraCore/wiki/Building-ChakraCore)
-You can build ChakraCore on Windows 7 SP1 or above, and Windows Server 2008 R2 or above, with either Visual Studio 2013 or 2015 with C++ support installed. Once you have Visual Studio installed:
+You can build ChakraCore on Windows 7 SP1 or above, and Windows Server 2008 R2 or above, with either Visual Studio 2015 or 2017 with C++ support installed. Once you have Visual Studio installed:
* Clone ChakraCore through ```git clone https://github.com/Microsoft/ChakraCore.git```
* Open `Build\Chakra.Core.sln` in Visual Studio
diff --git a/deps/chakrashim/core/RegenAllByteCode.cmd b/deps/chakrashim/core/RegenAllByteCode.cmd
index 1e7854be3db..11257f22361 100644
--- a/deps/chakrashim/core/RegenAllByteCode.cmd
+++ b/deps/chakrashim/core/RegenAllByteCode.cmd
@@ -38,6 +38,14 @@ if %errorlevel% neq 0 (
)
popd
+pushd lib\Runtime\Library\JsBuiltIn
+call GenByteCode.cmd
+if %errorlevel% neq 0 (
+ echo There was an error when regenerating bytecode header.
+ exit /b 1
+)
+popd
+
:: ch.exe x64_debug (NoJIT)
:: ch.exe x86_debug (NoJIT)
call jenkins\buildone.cmd x64 debug "/p:BuildJIT=false"
@@ -61,6 +69,15 @@ if %errorlevel% neq 0 (
)
popd
+:: Generate BuiltIn NoJIT Bytecodes using ch.exe (NoJIT)
+pushd lib\Runtime\Library\JsBuiltIn
+call GenByteCode.cmd -nojit
+if %errorlevel% neq 0 (
+ echo There was an error when regenerating bytecode header for NoJIT.
+ exit /b 1
+)
+popd
+
popd
endlocal
diff --git a/deps/chakrashim/core/bin/ChakraCore/ChakraCore.def b/deps/chakrashim/core/bin/ChakraCore/ChakraCore.def
index 1602aa1de4c..ca2a01dd616 100644
--- a/deps/chakrashim/core/bin/ChakraCore/ChakraCore.def
+++ b/deps/chakrashim/core/bin/ChakraCore/ChakraCore.def
@@ -55,3 +55,8 @@ JsInitializeJITServer
JsCreateSharedArrayBufferWithSharedContent
JsGetSharedArrayBufferContent
JsReleaseSharedArrayBufferContentHandle
+
+JsLessThan
+JsLessThanOrEqual
+
+JsCreateEnhancedFunction
diff --git a/deps/chakrashim/core/bin/ChakraCore/ChakraCore.vcxproj b/deps/chakrashim/core/bin/ChakraCore/ChakraCore.vcxproj
index 0b6b5add204..07504c0d7ec 100644
--- a/deps/chakrashim/core/bin/ChakraCore/ChakraCore.vcxproj
+++ b/deps/chakrashim/core/bin/ChakraCore/ChakraCore.vcxproj
@@ -155,7 +155,7 @@
{706083f7-6aa4-4558-a153-6352ef9110f5}
-
+
{8C61E4E7-F0D6-420D-A352-3E6E50D406DD}
diff --git a/deps/chakrashim/core/bin/GCStress/GCStress.cpp b/deps/chakrashim/core/bin/GCStress/GCStress.cpp
index bf6219dbe71..99228c4437b 100644
--- a/deps/chakrashim/core/bin/GCStress/GCStress.cpp
+++ b/deps/chakrashim/core/bin/GCStress/GCStress.cpp
@@ -214,16 +214,24 @@ void BuildObjectCreationTable()
objectCreationTable.AddWeightedEntry(&ScannedObject<1, 50>::New, 10000);
objectCreationTable.AddWeightedEntry(&BarrierObject<1, 50>::New, 2000);
objectCreationTable.AddWeightedEntry(&TrackedObject<1, 50>::New, 2000);
+#ifdef RECYCLER_VISITED_HOST
+ objectCreationTable.AddWeightedEntry(&RecyclerVisitedObject<1, 50>::New, 2000);
+#endif
objectCreationTable.AddWeightedEntry(&LeafObject<51, 1000>::New, 10);
objectCreationTable.AddWeightedEntry(&ScannedObject<51, 1000>::New, 100);
objectCreationTable.AddWeightedEntry(&BarrierObject<51, 1000>::New, 20);
objectCreationTable.AddWeightedEntry(&TrackedObject<51, 1000>::New, 20);
+#ifdef RECYCLER_VISITED_HOST
+ objectCreationTable.AddWeightedEntry(&RecyclerVisitedObject<51, 1000>::New, 40);
+#endif
objectCreationTable.AddWeightedEntry(&LeafObject<1001, 50000>::New, 1);
objectCreationTable.AddWeightedEntry(&ScannedObject<1001, 50000>::New, 10);
objectCreationTable.AddWeightedEntry(&BarrierObject<1001, 50000>::New, 2);
+ objectCreationTable.AddWeightedEntry(&FinalizedObject<1001, 50000>::New, 2);
// objectCreationTable.AddWeightedEntry(&TrackedObject<1001, 50000>::New, 2); // Large tracked objects are not supported
+// objectCreationTable.AddWeightedEntry(&RecyclerVisitedObject<1001, 50000>::New, 2); // Large recycler visited objects are not supported
}
void BuildOperationTable()
diff --git a/deps/chakrashim/core/bin/GCStress/GCStress.vcxproj b/deps/chakrashim/core/bin/GCStress/GCStress.vcxproj
index 9bd30b8688d..ab12e487c29 100644
--- a/deps/chakrashim/core/bin/GCStress/GCStress.vcxproj
+++ b/deps/chakrashim/core/bin/GCStress/GCStress.vcxproj
@@ -33,7 +33,7 @@
$(ChakraCommonLinkDependencies);
Advapi32.lib;
%(AdditionalDependencies)
- $(OutDir);%(AdditionalLibraryDirectories)
+ $(OutDir);%(AdditionalLibraryDirectories);$(SdkLibPath)
Console
diff --git a/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.cpp b/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.cpp
index fbf9f442bb7..1e7564c6335 100644
--- a/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.cpp
+++ b/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.cpp
@@ -10,6 +10,8 @@ size_t RecyclerTestObject::walkObjectCount = 0;
size_t RecyclerTestObject::walkScannedByteCount = 0;
size_t RecyclerTestObject::walkBarrierByteCount = 0;
size_t RecyclerTestObject::walkTrackedByteCount = 0;
+size_t RecyclerTestObject::walkFinalizedByteCount = 0;
+size_t RecyclerTestObject::walkRecyclerVisitedByteCount = 0;
size_t RecyclerTestObject::walkLeafByteCount = 0;
size_t RecyclerTestObject::currentWalkDepth = 0;
size_t RecyclerTestObject::maxWalkDepth = 0;
diff --git a/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.h b/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.h
index 1f0004ad2c1..496eba58474 100644
--- a/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.h
+++ b/deps/chakrashim/core/bin/GCStress/RecyclerTestObject.h
@@ -4,7 +4,9 @@
//-------------------------------------------------------------------------------------------------------
#include "stdafx.h"
-class RecyclerTestObject : public FinalizableObject
+#include "Core/RecyclerHeapMarkingContext.h"
+
+class RecyclerTestObject : public IRecyclerVisitedObject
{
protected:
RecyclerTestObject()
@@ -13,10 +15,16 @@ class RecyclerTestObject : public FinalizableObject
}
public:
- // FinalizableObject implementation
+ // IRecyclerVisitedObject implementation. We don't use FinalizableObject here as
+ // RecyclerVisitedObjects need to have Trace called on them, which is not allowed for
+ // FinalizableObject.
virtual void Finalize(bool isShutdown) override { VerifyCondition(false); };
virtual void Dispose(bool isShutdown) override { VerifyCondition(false); };
- virtual void Mark(Recycler * recycler) override { VerifyCondition(false); };
+ virtual void OnMark() override {}
+ virtual void Mark(RecyclerHeapHandle recycler) override { Mark(static_cast(recycler)); };
+ virtual void Trace(IRecyclerHeapMarkingContext* markContext) override { VerifyCondition(false); };
+
+ virtual void Mark(Recycler * recycler) { VerifyCondition(false); };
public:
static void BeginWalk()
@@ -27,13 +35,15 @@ class RecyclerTestObject : public FinalizableObject
walkScannedByteCount = 0;
walkBarrierByteCount = 0;
walkTrackedByteCount = 0;
+ walkFinalizedByteCount = 0;
+ walkRecyclerVisitedByteCount = 0;
walkLeafByteCount = 0;
maxWalkDepth = 0;
currentWalkDepth = 0;
wprintf(_u("-------------------------------------------\n"));
- wprintf(_u("Full heap walk starting\n"));
+ wprintf(_u("Full heap walk starting. Current generation: %12llu\n"), (unsigned long long) currentGeneration);
}
static void WalkReference(RecyclerTestObject * object)
@@ -66,13 +76,15 @@ class RecyclerTestObject : public FinalizableObject
VerifyCondition(currentWalkDepth == 0);
wprintf(_u("Full heap walk finished\n"));
- wprintf(_u("Object Count: %12llu\n"), (unsigned long long) walkObjectCount);
- wprintf(_u("Scanned Bytes: %12llu\n"), (unsigned long long) walkScannedByteCount);
- wprintf(_u("Barrier Bytes: %12llu\n"), (unsigned long long) walkBarrierByteCount);
- wprintf(_u("Tracked Bytes: %12llu\n"), (unsigned long long) walkTrackedByteCount);
- wprintf(_u("Leaf Bytes: %12llu\n"), (unsigned long long) walkLeafByteCount);
- wprintf(_u("Total Bytes: %12llu\n"), (unsigned long long) (walkScannedByteCount + walkBarrierByteCount + walkTrackedByteCount + walkLeafByteCount));
- wprintf(_u("Max Depth: %12llu\n"), (unsigned long long) maxWalkDepth);
+ wprintf(_u("Object Count: %12llu\n"), (unsigned long long) walkObjectCount);
+ wprintf(_u("Scanned Bytes: %12llu\n"), (unsigned long long) walkScannedByteCount);
+ wprintf(_u("Barrier Bytes: %12llu\n"), (unsigned long long) walkBarrierByteCount);
+ wprintf(_u("Tracked Bytes: %12llu\n"), (unsigned long long) walkTrackedByteCount);
+ wprintf(_u("Finalized Bytes: %12llu\n"), (unsigned long long) walkFinalizedByteCount);
+ wprintf(_u("RecyclerVisited Bytes: %12llu\n"), (unsigned long long) walkRecyclerVisitedByteCount);
+ wprintf(_u("Leaf Bytes: %12llu\n"), (unsigned long long) walkLeafByteCount);
+ wprintf(_u("Total Bytes: %12llu\n"), (unsigned long long) (walkScannedByteCount + walkBarrierByteCount + walkTrackedByteCount + walkFinalizedByteCount + walkLeafByteCount + walkRecyclerVisitedByteCount));
+ wprintf(_u("Max Depth: %12llu\n"), (unsigned long long) maxWalkDepth);
}
// Virtual methods
@@ -100,6 +112,8 @@ class RecyclerTestObject : public FinalizableObject
static size_t walkLeafByteCount;
static size_t walkBarrierByteCount;
static size_t walkTrackedByteCount;
+ static size_t walkFinalizedByteCount;
+ static size_t walkRecyclerVisitedByteCount;
static size_t currentWalkDepth;
static size_t maxWalkDepth;
@@ -232,8 +246,13 @@ class BarrierObject : public RecyclerTestObject
FieldNoBarrier(RecyclerTestObject *) references[0]; // SWB-TODO: is this correct?
};
+// TrackedObject must be a FinalizableObject (in order to be 'new'ed with RecyclerNewTrackedLeafPlusZ)
+// but it also must be a RecyclerTestObject to participate in GCStress. It must inherit from RecyclerTestObject
+// first so that the algined pointer is returned from New.
+// Fortunately, the v-tables for RecyclerTestObject and FinalizableObject line up, so the
+// IRecyclerVisitedObject/FinalizableObject calls end up in the right place.
template
-class TrackedObject : public RecyclerTestObject
+class TrackedObject : public RecyclerTestObject, public FinalizableObject
{
private:
TrackedObject(unsigned int count) :
@@ -295,4 +314,178 @@ class TrackedObject : public RecyclerTestObject
FieldNoBarrier(RecyclerTestObject *) references[0]; // SWB-TODO: is this correct?
};
+// A type of object that is finalizable, but not traced/tracked so that it can be used to test finalization
+// for LargeHeapBlock (which currently supports the FinalizeBit, but not TrackBit)
+template
+class FinalizedObject : public RecyclerTestObject, public FinalizableObject
+{
+private:
+ FinalizedObject(unsigned int count) :
+ count(count)
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ references[i] = nullptr;
+ }
+ }
+
+public:
+ static RecyclerTestObject * New()
+ {
+ unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
+
+ return RecyclerNewFinalizedPlus(recyclerInstance, sizeof(RecyclerTestObject *) * count, FinalizedObject, count);
+ }
+
+ virtual bool TryGetRandomLocation(Location * location) override
+ {
+ // Get a random slot and construct a Location for it
+ *location = Location::Scanned(&references[GetRandomInteger(count)]);
+
+ return true;
+ }
+
+ virtual void Mark(Recycler * recycler) override { VerifyCondition(false); };
+
+ // Finalize implementation.
+ virtual void Finalize(bool isShutdown) override { }
+ virtual void Dispose(bool isShutdown) override { }
+
+
+protected:
+ virtual void DoWalkObject() override
+ {
+ walkFinalizedByteCount += sizeof(FinalizedObject) + count * sizeof(RecyclerTestObject *);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ RecyclerTestObject::WalkReference(references[i]);
+ }
+ }
+
+private:
+ Field(unsigned int) count;
+ FieldNoBarrier(RecyclerTestObject *) references[0]; // SWB-TODO: is this correct?
+};
+
+#ifdef RECYCLER_VISITED_HOST
+
+template
+class RecyclerVisitedObject : public RecyclerTestObject
+{
+public:
+ static RecyclerTestObject * New()
+ {
+ // Determine a random amount of RecyclerTestObject* references to influence the size of this object.
+ const unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
+
+ void* mem = nullptr;
+ const size_t size = sizeof(RecyclerVisitedObject) + (sizeof(RecyclerTestObject*) * count);
+
+ // Randomly select the type of object to create
+ AllocationType allocType = static_cast(GetRandomInteger(static_cast(AllocationType::Count)));
+ switch (allocType)
+ {
+ case AllocationType::TraceAndFinalized:
+ mem = RecyclerAllocVisitedHostTracedAndFinalizedZero(recyclerInstance, size);
+ break;
+ case AllocationType::TraceOnly:
+ mem = RecyclerAllocVisitedHostTracedZero(recyclerInstance, size);
+ break;
+ case AllocationType::FinalizeLeaf:
+ mem = RecyclerAllocVisitedHostFinalizedZero(recyclerInstance, size);
+ break;
+ default:
+ Assert(allocType == AllocationType::Leaf);
+ mem = RecyclerAllocLeafZero(recyclerInstance, size);
+ }
+
+ // Construct the v-table, allocType, and count information for the new object.
+ RecyclerVisitedObject* obj = new (mem) RecyclerVisitedObject(allocType, count);
+ return obj;
+ }
+
+ virtual bool TryGetRandomLocation(Location * location) override
+ {
+ // Leaf types should not return a location
+ if (type == AllocationType::Leaf || type == AllocationType::FinalizeLeaf)
+ {
+ return false;
+ }
+
+ // Get a random slot and construct a Location for it
+ // Make this a Tagged location so that we won't inadvertently keep objects alive
+ // in the case where this object gets put on the wrong mark stack.
+ *location = Location::Tagged(&references[GetRandomInteger(count)]);
+
+ return true;
+ }
+
+ virtual void Trace(IRecyclerHeapMarkingContext* markContext) override
+ {
+ VerifyCondition(type == AllocationType::TraceAndFinalized || type == AllocationType::TraceOnly);
+ // Note that the pointers in the references arrary are technically tagged. However, this is ok
+ // as the Mark that we're performing is an interior mark, which gets us to the right object(s).
+ markContext->MarkObjects(reinterpret_cast(&references[0]), count, this);
+ }
+
+ virtual void Finalize(bool isShutdown) override
+ {
+ // Only types that request finalization should have Finalize called
+ VerifyCondition(IsFinalizable());
+ }
+ virtual void Dispose(bool isShutdown) override
+ {
+ // Only types that request finalization should have Finalize called
+ VerifyCondition(IsFinalizable());
+ VerifyCondition(unmanagedResource != nullptr);
+ BOOL success = ::HeapFree(GetProcessHeap(), 0, unmanagedResource);
+ VerifyCondition(success != FALSE);
+ unmanagedResource = nullptr;
+ }
+
+protected:
+ virtual void DoWalkObject() override
+ {
+ walkRecyclerVisitedByteCount += sizeof(RecyclerVisitedObject) + count * sizeof(RecyclerTestObject *);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ RecyclerTestObject::WalkReference(Location::Untag(references[i]));
+ }
+ }
+
+private:
+ enum class AllocationType : unsigned int
+ {
+ TraceAndFinalized = 0,
+ TraceOnly,
+ FinalizeLeaf,
+ Leaf,
+ Count,
+ };
+
+ bool IsFinalizable() const { return type == AllocationType::TraceAndFinalized || type == AllocationType::FinalizeLeaf; }
+ RecyclerVisitedObject(AllocationType allocType, unsigned int count) :
+ count(count),
+ type(allocType)
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ references[i] = nullptr;
+ }
+ if (IsFinalizable())
+ {
+ unmanagedResource = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, GetRandomInteger(1024));
+ VerifyCondition(unmanagedResource != nullptr);
+ }
+ }
+
+
+ Field(AllocationType) type;
+ Field(void*) unmanagedResource;
+ Field(unsigned int) count;
+ FieldNoBarrier(RecyclerTestObject *) references[0]; // SWB-TODO: is this correct? (copied from TrackedObject)
+};
+#endif
diff --git a/deps/chakrashim/core/bin/GCStress/StubExternalApi.cpp b/deps/chakrashim/core/bin/GCStress/StubExternalApi.cpp
index 78669cae0c1..cac9b97c7af 100644
--- a/deps/chakrashim/core/bin/GCStress/StubExternalApi.cpp
+++ b/deps/chakrashim/core/bin/GCStress/StubExternalApi.cpp
@@ -21,7 +21,7 @@ void ConfigParserAPI::DisplayInitialOutput(__in LPWSTR moduleName)
Output::Print(_u("INIT: DLL Path : %s\n"), moduleName);
}
-#ifdef ENABLE_JS_ETW
+#if defined(ENABLE_JS_ETW) && !defined(ENABLE_JS_LTTNG)
void EtwCallbackApi::OnSessionChange(ULONG /* controlCode */, PVOID /* callbackContext */)
{
// Does nothing
diff --git a/deps/chakrashim/core/bin/NativeTests/CodexTests.cpp b/deps/chakrashim/core/bin/NativeTests/CodexTests.cpp
index c521bfde5e1..3c6ad6fc718 100644
--- a/deps/chakrashim/core/bin/NativeTests/CodexTests.cpp
+++ b/deps/chakrashim/core/bin/NativeTests/CodexTests.cpp
@@ -84,7 +84,7 @@ namespace CodexTest
{
// Each of these test cases verifies the encoding
// of a single surrogate pair into a 6 byte CESU string
- // Each surrogate-pair unit is encoded seperately into utf8
+ // Each surrogate-pair unit is encoded separately into utf8
struct TestCase
{
char16 surrogatePair[2];
diff --git a/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.cpp b/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.cpp
new file mode 100644
index 00000000000..5eadeba79b3
--- /dev/null
+++ b/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.cpp
@@ -0,0 +1,345 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+#include "stdafx.h"
+#include "catch.hpp"
+#include "FunctionExecutionTest.h"
+
+// Definition of tests that exercise FunctionExecutionStateMachine
+namespace FunctionExecutionTest
+{
+ // Simple test case to validate that the state machine was created.
+ TEST_CASE("FuncExe_BasicTest")
+ {
+ Js::FunctionExecutionStateMachine f;
+ Js::FunctionBody body(false, false, false);
+ f.InitializeExecutionModeAndLimits(&body);
+ CHECK(f.GetExecutionMode() == ExecutionMode::Interpreter);
+ }
+
+ // Mimics script that repeatedly calls a function (not in a loop, but multiple times). This pattern hits all execution modes:
+ //ExecutionMode - function : testfn((#1.1), #2), mode : AutoProfilingInterpreter, size : 36, limits : 12.4.89.21.0 = 126, event : IsSpeculativeJitCandidate(before)
+ //ExecutionMode - function : testfn((#1.1), #2), mode : AutoProfilingInterpreter, size : 36, limits : 0.4.101.21.0 = 126, event : IsSpeculativeJitCandidate
+ //ExecutionMode - function : testfn((#1.1), #2), mode : ProfilingInterpreter, size : 36, limits : 0.4.101.21.0 = 126
+ //ExecutionMode - function : testfn((#1.1), #2), mode : AutoProfilingInterpreter, size : 36, limits : 0.0.101.21.0 = 122
+ //ExecutionMode - function : testfn((#1.1), #2), mode : SimpleJit, size : 36, limits : 0.0.0.21.0 = 21
+ //ExecutionMode - function : testfn((#1.1), #2), mode : SimpleJit, size : 36, limits : 0.0.0.21.0 = 21
+ //ExecutionMode - function : testfn((#1.1), #2), mode : FullJit, size : 36, limits : 0.0.0.0.0 = 0
+ template
+ void NormalExecution()
+ {
+ bool prevValue = FullJitPhaseOffFlag;
+ FullJitPhaseOffFlag = TFullJitPhase;
+
+ // Setup the function environment
+ int calls = 0;
+ Js::Configuration::Global.flags.SetDefaults();
+ Js::FunctionExecutionStateMachine f;
+ Js::FunctionBody body(true, true, true);
+
+ // Transition from Interpreter to AutoProfilingInterpreter
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //02 chakra!Js::FunctionBody::MarkScript
+ //03 chakra!Js::ByteCodeWriter::End
+ //04 chakra!ByteCodeGenerator::EmitOneFunction
+ //05 chakra!ByteCodeGenerator::EmitScopeList
+ //06 chakra!ByteCodeGenerator::EmitScopeList
+ //07 chakra!ByteCodeGenerator::EmitScopeList
+ //08 chakra!ByteCodeGenerator::EmitProgram
+ //09 chakra!ByteCodeGenerator::Generate
+ //0a chakra!GenerateByteCode
+ //0b chakra!ScriptEngine::CompileUTF8Core
+ //0c chakra!ScriptEngine::CompileUTF8
+ //0d chakra!ScriptEngine::DefaultCompile
+ //0e chakra!ScriptEngine::CreateScriptBody
+ //0f chakra!ScriptEngine::ParseScriptTextCore
+ //10 chakra!ScriptEngine::ParseScriptText
+ f.InitializeExecutionModeAndLimits(&body);
+ CHECK(f.GetExecutionMode() == ExecutionMode::AutoProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 0);
+ f.PrintLimits();
+
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextInterpreterExecutionMode
+ //03 chakra!Js::FunctionExecutionStateMachine::SetIsSpeculativeJitCandidate
+ //04 chakra!Js::FunctionBody::SetIsSpeculativeJitCandidate
+ //05 chakra!CodeGenWorkItem::ShouldSpeculativelyJitBasedOnProfile
+ //06 chakra!CodeGenWorkItem::ShouldSpeculativelyJit
+ //07 chakra!NativeCodeGenerator::GetJobToProcessProactively
+ //08 chakra!JsUtil::ForegroundJobProcessor::PrioritizeManagerAndWait
+ //09 chakra!JsUtil::JobProcessor::PrioritizeManagerAndWait
+ //0a chakra!NativeCodeGenerator::EnterScriptStart
+ //0b chakra!NativeCodeGenEnterScriptStart
+ //0c chakra!Js::ScriptContext::OnScriptStart
+ //0d chakra!Js::JavascriptFunction::CallRootFunctionInternal
+ //0e chakra!Js::JavascriptFunction::CallRootFunction
+ //0f chakra!ScriptSite::CallRootFunction
+ //10 chakra!ScriptSite::Execute
+ //11 chakra!ScriptEngine::ExecutePendingScripts
+ //12 chakra!ScriptEngine::ParseScriptTextCore
+ //13 chakra!ScriptEngine::ParseScriptText
+ f.SetIsSpeculativeJitCandidate();
+ CHECK(f.GetExecutionMode() == ExecutionMode::ProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // "Run" the function in the interpreter
+ for (; calls < 4; calls++)
+ {
+ f.IncreaseInterpretedCount();
+ }
+ CHECK(f.GetExecutionMode() == ExecutionMode::ProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 4);
+
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToJitExecutionMode
+ //03 chakra!Js::FunctionBody::TryTransitionToJitExecutionMode
+ //04 chakra!NativeCodeGenerator::Prioritize
+ //05 chakra!JsUtil::ForegroundJobProcessor::PrioritizeJob
+ //06 chakra!JsUtil::JobProcessor::PrioritizeJob
+ //07 chakra!NativeCodeGenerator::CheckCodeGen
+ //08 chakra!NativeCodeGenerator::CheckCodeGenThunk
+ //09 chakra!amd64_CallFunction
+ //0a chakra!Js::JavascriptFunction::CallFunction<1>
+ //0b chakra!Js::InterpreterStackFrame::OP_CallCommon > > >
+ //0c chakra!Js::InterpreterStackFrame::OP_CallI > > >
+ //0d chakra!Js::InterpreterStackFrame::ProcessUnprofiled
+ //0e chakra!Js::InterpreterStackFrame::Process
+ //0f chakra!Js::InterpreterStackFrame::InterpreterHelper
+ //10 chakra!Js::InterpreterStackFrame::InterpreterThunk
+ //11 0x0
+ //12 chakra!amd64_CallFunction
+ //13 chakra!Js::JavascriptFunction::CallFunction<1>
+ //14 chakra!Js::JavascriptFunction::CallRootFunctionInternal
+ //15 chakra!Js::JavascriptFunction::CallRootFunction
+ //16 chakra!ScriptSite::CallRootFunction
+ //17 chakra!ScriptSite::Execute
+ //18 chakra!ScriptEngine::ExecutePendingScripts
+ //19 chakra!ScriptEngine::ParseScriptTextCore
+ //1a chakra!ScriptEngine::ParseScriptText
+ f.TryTransitionToJitExecutionMode();
+ CHECK(f.GetExecutionMode() == ExecutionMode::AutoProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // "Run" the function in the interpreter
+ for (; calls < 105; calls++)
+ {
+ f.IncreaseInterpretedCount();
+ }
+ CHECK(f.GetExecutionMode() == ExecutionMode::AutoProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 0x65);
+
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToJitExecutionMode
+ //03 chakra!Js::FunctionBody::TryTransitionToJitExecutionMode
+ //04 chakra!NativeCodeGenerator::Prioritize
+ //05 chakra!JsUtil::ForegroundJobProcessor::PrioritizeJob
+ //06 chakra!JsUtil::JobProcessor::PrioritizeJob
+ //07 chakra!NativeCodeGenerator::CheckCodeGen
+ //08 chakra!NativeCodeGenerator::CheckCodeGenThunk
+ //09 chakra!amd64_CallFunction
+ //0a chakra!Js::JavascriptFunction::CallFunction<1>
+ //0b chakra!Js::InterpreterStackFrame::OP_CallCommon > > >
+ //0c chakra!Js::InterpreterStackFrame::OP_CallI > > >
+ //0d chakra!Js::InterpreterStackFrame::ProcessUnprofiled
+ //0e chakra!Js::InterpreterStackFrame::Process
+ //0f chakra!Js::InterpreterStackFrame::InterpreterHelper
+ //10 chakra!Js::InterpreterStackFrame::InterpreterThunk
+ //11 0x0
+ //12 chakra!amd64_CallFunction
+ //13 chakra!Js::JavascriptFunction::CallFunction<1>
+ //14 chakra!Js::JavascriptFunction::CallRootFunctionInternal
+ //15 chakra!Js::JavascriptFunction::CallRootFunction
+ //16 chakra!ScriptSite::CallRootFunction
+ //17 chakra!ScriptSite::Execute
+ //18 chakra!ScriptEngine::ExecutePendingScripts
+ //19 chakra!ScriptEngine::ParseScriptTextCore
+ //1a chakra!ScriptEngine::ParseScriptText
+ f.TryTransitionToJitExecutionMode();
+ CHECK(f.GetExecutionMode() == ExecutionMode::SimpleJit);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // Simple JIT EntryPoint Info keeps a count from the limit and decrements per call.
+ // Since the stub entry point is initialized to 0, proceed with transition.
+
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionBody::TryTransitionToNextExecutionMode
+ //03 chakra!NativeCodeGenerator::TransitionFromSimpleJit
+ //04 chakra!NativeCodeGenerator::Jit_TransitionFromSimpleJit
+ //05 0x0
+ //06 chakra!amd64_CallFunction
+ //07 chakra!Js::JavascriptFunction::CallFunction<1>
+ //08 chakra!Js::InterpreterStackFrame::OP_CallCommon > > >
+ //09 chakra!Js::InterpreterStackFrame::OP_CallI > > >
+ //0a chakra!Js::InterpreterStackFrame::ProcessUnprofiled
+ //0b chakra!Js::InterpreterStackFrame::Process
+ //0c chakra!Js::InterpreterStackFrame::InterpreterHelper
+ //0d chakra!Js::InterpreterStackFrame::InterpreterThunk
+ //0e 0x0
+ //0f chakra!amd64_CallFunction
+ //10 chakra!Js::JavascriptFunction::CallFunction<1>
+ //11 chakra!Js::JavascriptFunction::CallRootFunctionInternal
+ //12 chakra!Js::JavascriptFunction::CallRootFunction
+ //13 chakra!ScriptSite::CallRootFunction
+ //14 chakra!ScriptSite::Execute
+ //15 chakra!ScriptEngine::ExecutePendingScripts
+ //16 chakra!ScriptEngine::ParseScriptTextCore
+ //17 chakra!ScriptEngine::ParseScriptText
+ f.TryTransitionToNextExecutionMode();
+ CHECK(f.GetExecutionMode() == TFinalMode);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ FullJitPhaseOffFlag = prevValue;
+ }
+
+ TEST_CASE("FuncExe_NormalExecution")
+ {
+ NormalExecution();
+ }
+
+ TEST_CASE("FuncExe_NormalExecutionNoFullJit")
+ {
+ NormalExecution();
+ }
+
+ // test what happens when we jit a Loop Body
+ TEST_CASE("FuncExe_NormalExecutionOfLoop")
+ {
+
+ }
+
+ // Emulate/test what happens when we have the cmd args similar to JS unittests as Interpreted:
+ // -bvt -BaselineMode -DumpOnCrash -maxInterpretCount:1 -maxSimpleJitRunCount:1 -bgjit-
+ TEST_CASE("FuncExe_JSUnitTestInterpreted")
+ {
+ Js::Configuration::Global.flags.SetInterpretedValues();
+ Js::FunctionExecutionStateMachine f;
+ Js::FunctionBody body(true, true, true);
+
+ // to AutoProf
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //02 chakra!Js::FunctionBody::MarkScript
+ //03 chakra!Js::ByteCodeWriter::End
+ // ...and then to Prof
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextInterpreterExecutionMode
+ //03 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //04 chakra!Js::FunctionBody::MarkScript
+ //05 chakra!Js::ByteCodeWriter::End
+ f.InitializeExecutionModeAndLimits(&body);
+ CHECK(f.GetExecutionMode() == ExecutionMode::ProfilingInterpreter);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // Run the function once under the Interpreter
+ f.IncreaseInterpretedCount();
+
+ // to Simple
+ //# Call Site
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToJitExecutionMode
+ //03 chakra!Js::FunctionBody::TryTransitionToJitExecutionMode
+ //04 chakra!NativeCodeGenerator::CheckCodeGen
+ //05 chakra!NativeCodeGenerator::CheckCodeGenThunk
+ //06 chakra!amd64_CallFunction
+ f.TryTransitionToJitExecutionMode();
+ CHECK(f.GetExecutionMode() == ExecutionMode::SimpleJit);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // Simple JIT EntryPoint Info keeps a count from the limit and decrements per call.
+ // Since the stub entry point is initialized to 0, proceed with transition.
+
+ // to full
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionBody::TryTransitionToNextExecutionMode
+ //03 chakra!NativeCodeGenerator::TransitionFromSimpleJit
+ //04 chakra!NativeCodeGenerator::Jit_TransitionFromSimpleJit
+ f.TryTransitionToNextExecutionMode();
+ CHECK(f.GetExecutionMode() == ExecutionMode::FullJit);
+ CHECK(f.GetInterpretedCount() == 0);
+ }
+
+ // Emulate/test what happens when we have the cmd args similar to JS unittests as DynaPogo:
+ // -bvt -BaselineMode -DumpOnCrash -forceNative -off:simpleJit -bgJitDelay:0
+ template
+ void JSUnitTestDynapogo()
+ {
+ bool prevValue = FullJitPhaseOffFlag;
+ FullJitPhaseOffFlag = TFullJitPhase;
+
+ Js::Configuration::Global.flags.SetDynaPogoValues();
+ Js::FunctionExecutionStateMachine f;
+ Js::FunctionBody body(true, true, false);
+ // to AutoProf
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //02 chakra!Js::FunctionBody::MarkScript
+ //03 chakra!Js::ByteCodeWriter::End
+ // ...then FullJit
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextInterpreterExecutionMode
+ //03 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //04 chakra!Js::FunctionBody::MarkScript
+ //05 chakra!Js::ByteCodeWriter::End
+ // ..then profiling
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextInterpreterExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::InitializeExecutionModeAndLimits
+ //03 chakra!Js::FunctionBody::MarkScript
+ //04 chakra!Js::ByteCodeWriter::End
+ f.InitializeExecutionModeAndLimits(&body);
+ CHECK(f.GetExecutionMode() == TInitialMode);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ // to full
+ //00 chakra!Js::FunctionExecutionStateMachine::SetExecutionMode
+ //01 chakra!Js::FunctionExecutionStateMachine::TryTransitionToNextExecutionMode
+ //02 chakra!Js::FunctionExecutionStateMachine::TryTransitionToJitExecutionMode
+ //03 chakra!Js::FunctionBody::TryTransitionToJitExecutionMode
+ //04 chakra!NativeCodeGenerator::CheckCodeGen
+ //05 chakra!NativeCodeGenerator::CheckCodeGenThunk
+ f.TryTransitionToJitExecutionMode();
+ CHECK(f.GetExecutionMode() == TFinalMode);
+ CHECK(f.GetInterpretedCount() == 0);
+
+ FullJitPhaseOffFlag = prevValue;
+ }
+
+ TEST_CASE("FuncExe_JSUnitTestDynapogo")
+ {
+ JSUnitTestDynapogo();
+ }
+
+ TEST_CASE("FuncExe_JSUnitTestDynapogoNoFullJit")
+ {
+ JSUnitTestDynapogo();
+ }
+
+ // test what hits TransitionToSimpleJitExecutionMode
+ // NativeCodeGenerator::GenerateFunction with the following args
+ // -bgjit- -trace:executionmode -prejit -force:simplejit
+ TEST_CASE("FuncExe_TransitionToSimpleJit")
+ {
+
+ }
+
+ // test what hits TransitionToFullJitExecutionMode
+ // Note: also called from
+ // - BailOutRecord::ScheduleFunctionCodeGen, when we rejit after bailout
+ // - NativeCodeGenerator::GetJobToProcessProactively, looks like it's for speculative jit
+ // - NativeCodeGenerator::GenerateFunction, when prejitting with the following args
+ // -bgjit- -trace:executionmode -prejit
+ TEST_CASE("FuncExe_TransitionToFullJit")
+ {
+
+ }
+}
diff --git a/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.h b/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.h
new file mode 100644
index 00000000000..b3df9e59225
--- /dev/null
+++ b/deps/chakrashim/core/bin/NativeTests/FunctionExecutionTest.h
@@ -0,0 +1,139 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+// This file contains stubs needed to make FunctionExecutionTest successfully compile and link as well
+// as a means to emulate behavior of objects that interact with FunctionExecutionStateMachine
+
+#include "..\..\lib\Common\Core\CommonMinMax.h"
+
+#define ENUM_CLASS_HELPERS(x, y)
+#include "..\..\lib\Runtime\Language\ExecutionMode.h"
+
+#define FieldWithBarrier(type) type
+
+#define CONFIG_FLAG(flag) 10
+#define PHASE_OFF(foo, bar) FunctionExecutionTest::PhaseOff(foo, bar)
+#define PHASE_FORCE(foo, bar) false
+#define NewSimpleJit 1
+#define FullJitPhase 2
+#define DEFAULT_CONFIG_MinSimpleJitIterations 0
+
+namespace FunctionExecutionTest
+{
+ static bool FullJitPhaseOffFlag = false;
+ bool PhaseOff(int phase, void*)
+ {
+ if (phase == FullJitPhase)
+ {
+ return FullJitPhaseOffFlag;
+ }
+ else
+ {
+ Assert(!"Unknown Phase");
+ return false;
+ }
+ }
+}
+
+namespace Js
+{
+ class ConfigFlagsTable
+ {
+ public:
+ uint16 AutoProfilingInterpreter0Limit;
+ uint16 AutoProfilingInterpreter1Limit;
+ uint16 ProfilingInterpreter0Limit;
+ uint16 ProfilingInterpreter1Limit;
+ uint16 SimpleJitLimit;
+ bool EnforceExecutionModeLimits;
+
+ void SetDefaults()
+ {
+ AutoProfilingInterpreter0Limit = 0xc;
+ ProfilingInterpreter0Limit = 0x4;
+ AutoProfilingInterpreter1Limit = 0x44;
+ ProfilingInterpreter1Limit = 0;
+ SimpleJitLimit = 0x15;
+ EnforceExecutionModeLimits = false;
+ }
+
+ void SetInterpretedValues()
+ {
+ AutoProfilingInterpreter0Limit = 0;
+ AutoProfilingInterpreter1Limit = 0;
+ ProfilingInterpreter0Limit = 1;
+ ProfilingInterpreter1Limit = 0;
+ SimpleJitLimit = 1;
+ EnforceExecutionModeLimits = true;
+ }
+
+ void SetDynaPogoValues()
+ {
+ AutoProfilingInterpreter0Limit = 0;
+ AutoProfilingInterpreter1Limit = 0;
+ ProfilingInterpreter0Limit = 0;
+ ProfilingInterpreter1Limit = 0;
+ SimpleJitLimit = 0;
+ EnforceExecutionModeLimits = true;
+ }
+ };
+
+ enum Phase
+ {
+ SimpleJitPhase
+ };
+
+ class Configuration
+ {
+ public:
+ Configuration() {}
+ ConfigFlagsTable flags;
+ static Configuration Global;
+ };
+ Configuration Configuration::Global;
+
+ class FunctionEntryPointInfo
+ {
+ public:
+ FunctionEntryPointInfo() : callsCount(0) {}
+ int callsCount;
+ };
+
+ class Output
+ {
+ public:
+ static size_t Print(const char16 *form, ...) { UNREFERENCED_PARAMETER(form); return 0; }
+ };
+
+ class FunctionBody
+ {
+ public:
+ bool DoInterpreterProfile() const { return doInterpreterProfile; }
+ bool DoInterpreterAutoProfile() const { return doInterpreterAutoProfile; }
+ bool DoSimpleJit() const { return doSimpleJit; }
+ uint GetByteCodeCount() const { return 0; }
+ uint GetByteCodeInLoopCount() const { return 0; }
+ uint GetByteCodeWithoutLDACount() const { return 0; }
+ FunctionEntryPointInfo* GetDefaultFunctionEntryPointInfo() { return &defaultInfo; }
+ FunctionEntryPointInfo *GetSimpleJitEntryPointInfo() { return &simpleInfo; }
+ void TraceExecutionMode(const char *const eventDescription = nullptr) const { UNREFERENCED_PARAMETER(eventDescription); }
+
+ FunctionBody(bool interpreterProfile, bool interpreterAutoProfile, bool simpleJit):
+ doInterpreterProfile(interpreterProfile),
+ doInterpreterAutoProfile(interpreterAutoProfile),
+ doSimpleJit(simpleJit)
+ {}
+
+ private:
+ bool doInterpreterProfile;
+ bool doInterpreterAutoProfile;
+ bool doSimpleJit;
+ FunctionEntryPointInfo defaultInfo;
+ FunctionEntryPointInfo simpleInfo;
+ };
+}
+
+#include "..\..\lib\Runtime\Base\FunctionExecutionStateMachine.h"
+#include "..\..\lib\Runtime\Base\FunctionExecutionStateMachine.cpp"
diff --git a/deps/chakrashim/core/bin/NativeTests/JsRTApiTest.cpp b/deps/chakrashim/core/bin/NativeTests/JsRTApiTest.cpp
index e022f7908c4..d3f7b83ba50 100644
--- a/deps/chakrashim/core/bin/NativeTests/JsRTApiTest.cpp
+++ b/deps/chakrashim/core/bin/NativeTests/JsRTApiTest.cpp
@@ -660,6 +660,217 @@ namespace JsRTApiTest
JsRTApiTest::RunWithAttributes(JsRTApiTest::ExternalFunctionTest);
}
+ JsValueRef CALLBACK ExternalEnhancedFunctionTestCallback(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, JsNativeFunctionInfo *info, void *callbackData)
+ {
+ REQUIRE(callbackData != nullptr);
+ REQUIRE(*static_cast(callbackData) == 123);
+ REQUIRE(argumentCount == 2);
+
+ bool success = false;
+ JsValueRef _true;
+ REQUIRE(JsGetTrueValue(&_true) == JsNoError);
+ JsValueRef _false;
+ REQUIRE(JsGetFalseValue(&_false) == JsNoError);
+
+
+ REQUIRE(JsStrictEquals(_true, arguments[0], &success) == JsNoError);
+ REQUIRE(success);
+ REQUIRE(JsStrictEquals(_false, arguments[1], &success) == JsNoError);
+ REQUIRE(success);
+
+ REQUIRE(!info->isConstructCall);
+ REQUIRE(info->thisArg == arguments[0]);
+
+ JsValueRef undefined;
+ REQUIRE(JsGetUndefinedValue(&undefined) == JsNoError);
+ REQUIRE(JsStrictEquals(undefined, info->newTargetArg, &success) == JsNoError);
+ REQUIRE(success);
+
+ JsValueRef _null;
+ REQUIRE(JsGetNullValue(&_null) == JsNoError);
+ return _null;
+ }
+
+ JsValueRef CALLBACK ExternalEnhancedConstructorFunctionTestCallback(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, JsNativeFunctionInfo *info, void *callbackData)
+ {
+ REQUIRE(callbackData != nullptr);
+ REQUIRE(*static_cast(callbackData) == 456);
+ REQUIRE(argumentCount == 3);
+
+ bool success = false;
+ JsValueRef _true;
+ REQUIRE(JsGetTrueValue(&_true) == JsNoError);
+ JsValueRef _false;
+ REQUIRE(JsGetFalseValue(&_false) == JsNoError);
+ JsValueRef _null;
+ REQUIRE(JsGetNullValue(&_null) == JsNoError);
+
+ REQUIRE(info->thisArg == arguments[0]);
+ REQUIRE(JsStrictEquals(_true, arguments[1], &success) == JsNoError);
+ REQUIRE(success);
+ REQUIRE(JsStrictEquals(_false, arguments[2], &success) == JsNoError);
+ REQUIRE(success);
+
+ REQUIRE(info->isConstructCall);
+
+ JsValueType t;
+ REQUIRE(JsGetValueType(info->newTargetArg, &t) == JsNoError);
+ REQUIRE(t == JsFunction);
+ REQUIRE(JsGetValueType(info->thisArg, &t) == JsNoError);
+ REQUIRE(t == JsObject);
+
+ return info->thisArg;
+ }
+
+ void ExternalEnhancedFunctionTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
+ {
+ int sentinel = 123;
+ JsValueRef function = JS_INVALID_REFERENCE;
+ REQUIRE(JsCreateEnhancedFunction(ExternalEnhancedFunctionTestCallback, nullptr, &sentinel, &function) == JsNoError);
+ JsValueRef _true;
+ REQUIRE(JsGetTrueValue(&_true) == JsNoError);
+ JsValueRef _false;
+ REQUIRE(JsGetFalseValue(&_false) == JsNoError);
+ JsValueRef args[2] = { _true, _false };
+ JsValueRef _null;
+ REQUIRE(JsGetNullValue(&_null) == JsNoError);
+ JsValueRef result;
+ REQUIRE(JsCallFunction(function, args, 2, &result) == JsNoError);
+ bool success;
+ REQUIRE(JsStrictEquals(_null, result, &success) == JsNoError);
+ REQUIRE(success);
+
+ sentinel = 456;
+ function = JS_INVALID_REFERENCE;
+ REQUIRE(JsCreateEnhancedFunction(ExternalEnhancedConstructorFunctionTestCallback, nullptr, &sentinel, &function) == JsNoError);
+ JsValueRef ctorArgs[3] = { _null, _true, _false };
+ REQUIRE(JsConstructObject(function, ctorArgs, 3, &result) == JsNoError);
+ JsValueType t;
+ REQUIRE(JsGetValueType(result, &t) == JsNoError);
+ REQUIRE(t == JsObject);
+ }
+
+ TEST_CASE("ApiTest_ExternalEnhancedFunctionTest", "[ApiTest]")
+ {
+ JsRTApiTest::RunWithAttributes(JsRTApiTest::ExternalEnhancedFunctionTest);
+ }
+
+ struct ExternalEnhancedBaseClassFunctionTestInfo
+ {
+ JsValueRef derived;
+ JsValueRef base;
+ };
+
+ JsValueRef CALLBACK ExternalEnhancedBaseClassFunctionTestCallback(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, JsNativeFunctionInfo *info, void *callbackData)
+ {
+ REQUIRE(callbackData != nullptr);
+
+ ExternalEnhancedBaseClassFunctionTestInfo* testinfo = (ExternalEnhancedBaseClassFunctionTestInfo*)callbackData;
+ JsValueType t;
+ REQUIRE(JsGetValueType(testinfo->derived, &t) == JsNoError);
+ REQUIRE(t == JsFunction);
+ REQUIRE(JsGetValueType(testinfo->base, &t) == JsNoError);
+ REQUIRE(t == JsFunction);
+ REQUIRE(argumentCount == 2);
+
+ JsPropertyIdRef propId;
+ bool success = false;
+ JsValueRef _true;
+ REQUIRE(JsGetTrueValue(&_true) == JsNoError);
+ JsValueRef _false;
+ REQUIRE(JsGetFalseValue(&_false) == JsNoError);
+
+ REQUIRE(info->thisArg == arguments[0]);
+ REQUIRE(JsStrictEquals(_true, arguments[1], &success) == JsNoError);
+ REQUIRE(success);
+
+ REQUIRE(info->isConstructCall);
+ REQUIRE(JsGetValueType(info->newTargetArg, &t) == JsNoError);
+ REQUIRE(t == JsFunction);
+ REQUIRE(JsGetValueType(info->thisArg, &t) == JsNoError);
+ REQUIRE(t == JsObject);
+
+ // new.target === Derived
+ REQUIRE(JsStrictEquals(info->newTargetArg, testinfo->derived, &success) == JsNoError);
+ REQUIRE(success);
+
+ // this.constructor === Derived
+ REQUIRE(JsGetPropertyIdFromName(_u("constructor"), &propId) == JsNoError);
+ JsValueRef thisCtor = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetProperty(info->thisArg, propId, &thisCtor) == JsNoError);
+ REQUIRE(JsStrictEquals(thisCtor, testinfo->derived, &success) == JsNoError);
+ REQUIRE(success);
+
+ // this.__proto__ === Derived.prototype
+ JsValueRef thisProto = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetPrototype(info->thisArg, &thisProto) == JsNoError);
+ JsValueRef derivedPrototype = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetPropertyIdFromName(_u("prototype"), &propId) == JsNoError);
+ REQUIRE(JsGetProperty(testinfo->derived, propId, &derivedPrototype) == JsNoError);
+ REQUIRE(JsStrictEquals(thisProto, derivedPrototype, &success) == JsNoError);
+ REQUIRE(success);
+
+ return info->thisArg;
+ }
+
+ void ExternalEnhancedBaseClassFunctionTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
+ {
+ ExternalEnhancedBaseClassFunctionTestInfo info = { nullptr, nullptr };
+ JsValueRef name = JS_INVALID_REFERENCE;
+ REQUIRE(JsCreateString("BaseClass", 10, &name) == JsNoError);
+ JsValueRef base = JS_INVALID_REFERENCE;
+ REQUIRE(JsCreateEnhancedFunction(ExternalEnhancedBaseClassFunctionTestCallback, name, &info, &base) == JsNoError);
+ info.base = base;
+
+ JsValueRef global = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetGlobalObject(&global) == JsNoError);
+ JsPropertyIdRef propId;
+ REQUIRE(JsGetPropertyIdFromName(_u("BaseClass"), &propId) == JsNoError);
+ REQUIRE(JsSetProperty(global, propId, base, false) == JsNoError);
+
+ bool success = false;
+ JsValueType t;
+ JsValueRef derived = JS_INVALID_REFERENCE;
+ REQUIRE(JsRunScript(
+ _u("class Derived extends BaseClass {") \
+ _u(" constructor() {") \
+ _u(" super(true);") \
+ _u(" }") \
+ _u("};"), JS_SOURCE_CONTEXT_NONE, _u(""), &derived) == JsNoError);
+
+ info.derived = derived;
+ REQUIRE(JsGetValueType(derived, &t) == JsNoError);
+ REQUIRE(t == JsFunction);
+
+ JsValueRef instance = JS_INVALID_REFERENCE;
+ REQUIRE(JsRunScript(
+ _u("new Derived();"), JS_SOURCE_CONTEXT_NONE, _u(""), &instance) == JsNoError);
+
+ REQUIRE(JsGetValueType(instance, &t) == JsNoError);
+ REQUIRE(t == JsObject);
+
+ // instance.constructor === Derived
+ REQUIRE(JsGetPropertyIdFromName(_u("constructor"), &propId) == JsNoError);
+ JsValueRef instanceCtor = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetProperty(instance, propId, &instanceCtor) == JsNoError);
+ REQUIRE(JsStrictEquals(instanceCtor, derived, &success) == JsNoError);
+ REQUIRE(success);
+
+ // instance.__proto__ === Derived.prototype
+ JsValueRef instanceProto = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetPrototype(instance, &instanceProto) == JsNoError);
+ JsValueRef derivedPrototype = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetPropertyIdFromName(_u("prototype"), &propId) == JsNoError);
+ REQUIRE(JsGetProperty(derived, propId, &derivedPrototype) == JsNoError);
+ REQUIRE(JsStrictEquals(instanceProto, derivedPrototype, &success) == JsNoError);
+ REQUIRE(success);
+ }
+
+ TEST_CASE("ApiTest_ExternalEnhancedBaseClassFunctionTest", "[ApiTest]")
+ {
+ JsRTApiTest::RunWithAttributes(JsRTApiTest::ExternalEnhancedBaseClassFunctionTest);
+ }
+
void ExternalFunctionNameTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
auto testConstructorName = [=](JsValueRef function, PCWCHAR expectedName, size_t expectedNameLength)
@@ -2063,6 +2274,7 @@ namespace JsRTApiTest
JsRTApiTest::WithSetup(JsRuntimeAttributeEnableExperimentalFeatures, ReentrantParseModuleTest);
}
+
ModuleResponseData reentrantNoErrorParseData;
static JsErrorCode CALLBACK reentrantNoErrorParse_FIMC(_In_ JsModuleRecord referencingModule, _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
{
@@ -2131,6 +2343,50 @@ namespace JsRTApiTest
JsRTApiTest::WithSetup(JsRuntimeAttributeEnableExperimentalFeatures, ReentrantNoErrorParseModuleTest);
}
+ static JsErrorCode CALLBACK FIMC1(_In_ JsModuleRecord referencingModule, _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
+ {
+ JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
+ LPCWSTR specifierStr;
+ size_t length;
+ JsErrorCode errorCode = JsStringToPointer(specifier, &specifierStr, &length);
+ REQUIRE(errorCode == JsNoError);
+
+ if (wcscmp(specifierStr, _u("foo.js")) == 0)
+ {
+ errorCode = JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
+ REQUIRE(errorCode == JsNoError);
+ }
+
+ *dependentModuleRecord = moduleRecord;
+ return JsNoError;
+ }
+
+ static JsErrorCode CALLBACK NMRC1(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
+ {
+ // NotifyModuleReadyCallback handling.
+
+ return JsNoError;
+ }
+
+ void SomebugTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
+ {
+ JsModuleRecord rec;
+ JsInitializeModuleRecord(nullptr, nullptr, &rec);
+ JsSetModuleHostInfo(rec, JsModuleHostInfo_FetchImportedModuleCallback, FIMC1);
+ JsSetModuleHostInfo(rec, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, FIMC1);
+ JsSetModuleHostInfo(rec, JsModuleHostInfo_NotifyModuleReadyCallback, NMRC1);
+
+ JsValueRef F = JS_INVALID_REFERENCE;
+ JsErrorCode err = JsRunScript(_u("var j = import('foo.js').then(mod => { mod.bar(); })"), 0, _u(""), &F);
+
+ CHECK(err == JsNoError);
+ }
+
+ TEST_CASE("ApiTest_SomebugTest", "[ApiTest]")
+ {
+ JsRTApiTest::WithSetup(JsRuntimeAttributeEnableExperimentalFeatures, SomebugTest);
+
+ }
void ObjectHasOwnPropertyMethodTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
JsValueRef proto = JS_INVALID_REFERENCE;
@@ -2196,4 +2452,84 @@ namespace JsRTApiTest
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCopyStringOneByteMethodTest);
}
+ void JsLessThanTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
+ {
+ // Create some values
+ JsValueRef number1 = JS_INVALID_REFERENCE; // number1 = 1
+ REQUIRE(JsDoubleToNumber(1, &number1) == JsNoError);
+ JsValueRef number2 = JS_INVALID_REFERENCE; // number2 = 2
+ REQUIRE(JsDoubleToNumber(2, &number2) == JsNoError);
+ JsValueRef stringa = JS_INVALID_REFERENCE; // stringa = "1"
+ REQUIRE(JsPointerToString(_u("1"), wcslen(_u("1")), &stringa) == JsNoError);
+ JsValueRef undefined = GetUndefined();
+ JsValueRef nullValue = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetNullValue(&nullValue) == JsNoError);
+ JsValueRef trueValue = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetTrueValue(&trueValue) == JsNoError);
+ JsValueRef falseValue = JS_INVALID_REFERENCE;
+ REQUIRE(JsGetFalseValue(&falseValue) == JsNoError);
+
+ bool result;
+ REQUIRE(JsLessThan(number1, number2, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThan(number1, stringa, &result) == JsNoError);
+ CHECK(result == false);
+ REQUIRE(JsLessThan(number1, undefined, &result) == JsNoError);
+ CHECK(result == false);
+ REQUIRE(JsLessThan(falseValue, trueValue, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThan(undefined, undefined, &result) == JsNoError);
+ CHECK(result == false);
+ REQUIRE(JsLessThan(nullValue, undefined, &result) == JsNoError);
+ CHECK(result == false);
+
+ REQUIRE(JsLessThanOrEqual(number1, number2, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThanOrEqual(number1, number1, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThanOrEqual(number1, stringa, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThanOrEqual(trueValue, trueValue, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThanOrEqual(falseValue, nullValue, &result) == JsNoError);
+ CHECK(result == true);
+ REQUIRE(JsLessThanOrEqual(falseValue, undefined, &result) == JsNoError);
+ CHECK(result == false);
+ REQUIRE(JsLessThanOrEqual(undefined, undefined, &result) == JsNoError);
+ CHECK(result == false);
+ REQUIRE(JsLessThanOrEqual(nullValue, undefined, &result) == JsNoError);
+ CHECK(result == false);
+ }
+
+ TEST_CASE("ApiTest_JsLessThanTest", "[ApiTest]")
+ {
+ JsRTApiTest::RunWithAttributes(JsRTApiTest::JsLessThanTest);
+ }
+
+ void JsCreateStringTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
+ {
+ // Passing in invalid utf8 sequences should result in the unicode replacement character
+ const char invalidUtf8[] = { -127 /* 0x80 */, '\0' };
+ JsValueRef result;
+ REQUIRE(JsCreateString(invalidUtf8, 1, &result) == JsNoError);
+ uint16_t utf16Result[2];
+ size_t written;
+ REQUIRE(JsCopyStringUtf16(result, 0, 1, utf16Result, &written) == JsNoError);
+ CHECK(written == 1);
+ CHECK(utf16Result[0] == 0xFFFD);
+
+ // Creating a utf8 string and then copying it back out should give an identical string
+ // Specifying -1 as the length should result in using strlen as the length
+ const char validUtf8Input[] = {'T', 'e', 's', 't', ' ', -30 /* 0xe2 */, -104 /* 0x98 */, -125 /* 0x83 */, 0};
+ REQUIRE(JsCreateString(validUtf8Input, static_cast(-1), &result) == JsNoError);
+ char utf8Result[10];
+ REQUIRE(JsCopyString(result,utf8Result, 10, &written) == JsNoError);
+ CHECK(written == strlen(validUtf8Input));
+ CHECK(memcmp(utf8Result, validUtf8Input, written) == 0);
+ }
+
+ TEST_CASE("ApiTest_JsCreateStringTest", "[ApiTest]")
+ {
+ JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCreateStringTest);
+ }
}
diff --git a/deps/chakrashim/core/bin/NativeTests/NativeTests.vcxproj b/deps/chakrashim/core/bin/NativeTests/NativeTests.vcxproj
index d020992c672..6464afadf24 100644
--- a/deps/chakrashim/core/bin/NativeTests/NativeTests.vcxproj
+++ b/deps/chakrashim/core/bin/NativeTests/NativeTests.vcxproj
@@ -21,12 +21,13 @@
- $(ChakraCoreRootDirectory)Lib\Jsrt;
- $(MSBuildThisFileDirectory);
- $(ChakraCoreRootDirectory)Lib\Common;
- $(ChakraCoreRootDirectory)bin\External;
- %(AdditionalIncludeDirectories)
+ $(ChakraCoreRootDirectory)Lib\Jsrt;
+ $(MSBuildThisFileDirectory);
+ $(ChakraCoreRootDirectory)Lib\Common;
+ $(ChakraCoreRootDirectory)bin\External;
+ %(AdditionalIncludeDirectories)
+
true
false
false
@@ -42,9 +43,10 @@
+
-
+
diff --git a/deps/chakrashim/core/bin/NativeTests/Runtime.h b/deps/chakrashim/core/bin/NativeTests/Runtime.h
new file mode 100644
index 00000000000..ac4d2893da4
--- /dev/null
+++ b/deps/chakrashim/core/bin/NativeTests/Runtime.h
@@ -0,0 +1,7 @@
+//-------------------------------------------------------------------------------------------------------
+// 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
+
+// stub file for RuntimeBasePch.h
diff --git a/deps/chakrashim/core/bin/NativeTests/WasmReader.h b/deps/chakrashim/core/bin/NativeTests/WasmReader.h
new file mode 100644
index 00000000000..ac4d2893da4
--- /dev/null
+++ b/deps/chakrashim/core/bin/NativeTests/WasmReader.h
@@ -0,0 +1,7 @@
+//-------------------------------------------------------------------------------------------------------
+// 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
+
+// stub file for RuntimeBasePch.h
diff --git a/deps/chakrashim/core/bin/NativeTests/stdafx.h b/deps/chakrashim/core/bin/NativeTests/stdafx.h
index c9f5f1ce062..6f52ee986e2 100644
--- a/deps/chakrashim/core/bin/NativeTests/stdafx.h
+++ b/deps/chakrashim/core/bin/NativeTests/stdafx.h
@@ -23,6 +23,8 @@
#if defined(DBG)
+#define DebugOnly(x) x
+
#define AssertMsg(exp, comment) \
do { \
if (!(exp)) \
@@ -41,4 +43,4 @@ if (!(exp)) \
#include "chakracore.h"
#include "Core/CommonTypedefs.h"
-#include
+#include
\ No newline at end of file
diff --git a/deps/chakrashim/core/bin/ch/CMakeLists.txt b/deps/chakrashim/core/bin/ch/CMakeLists.txt
index e15fcc1fb68..210ee6d4ed7 100644
--- a/deps/chakrashim/core/bin/ch/CMakeLists.txt
+++ b/deps/chakrashim/core/bin/ch/CMakeLists.txt
@@ -63,9 +63,9 @@ if(STATIC_LIBRARY)
-Wl,-undefined,error
${LINKER_START_GROUP}
ChakraCoreStatic
+ ${ICULIB}
${LINKER_END_GROUP}
dl
- ${ICULIB}
)
if(CC_TARGET_OS_OSX)
diff --git a/deps/chakrashim/core/bin/ch/ChakraRtInterface.cpp b/deps/chakrashim/core/bin/ch/ChakraRtInterface.cpp
index 5102cd487da..191fa1c499f 100644
--- a/deps/chakrashim/core/bin/ch/ChakraRtInterface.cpp
+++ b/deps/chakrashim/core/bin/ch/ChakraRtInterface.cpp
@@ -6,6 +6,7 @@
#ifdef _WIN32
LPCSTR chakraDllName = "chakracore.dll";
+LPCWSTR chakraDllNameW = _u("chakracore.dll");
#else
#include
#ifdef __APPLE__
@@ -23,10 +24,12 @@ ChakraRTInterface::ArgInfo* ChakraRTInterface::m_argInfo = nullptr;
TestHooks ChakraRTInterface::m_testHooks = { 0 };
JsAPIHooks ChakraRTInterface::m_jsApiHooks = { 0 };
-LPCSTR GetChakraDllName()
+#ifdef _WIN32
+LPCWSTR GetChakraDllNameW()
{
- return chakraDllName;
+ return chakraDllNameW;
}
+#endif
// Wrapper functions to abstract out loading ChakraCore
// and resolving its symbols
diff --git a/deps/chakrashim/core/bin/ch/ChakraRtInterface.h b/deps/chakrashim/core/bin/ch/ChakraRtInterface.h
index e224cee5185..6dbc3f77bd2 100644
--- a/deps/chakrashim/core/bin/ch/ChakraRtInterface.h
+++ b/deps/chakrashim/core/bin/ch/ChakraRtInterface.h
@@ -8,7 +8,7 @@ struct JsAPIHooks
{
typedef JsErrorCode (WINAPI *JsrtCreateRuntimePtr)(JsRuntimeAttributes attributes, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime);
typedef JsErrorCode (WINAPI *JsrtCreateContextPtr)(JsRuntimeHandle runtime, JsContextRef *newContext);
- typedef JsErrorCode(WINAPI *JsrtSetObjectBeforeCollectCallbackPtr)(JsRef ref, void* callbackState, JsObjectBeforeCollectCallback objectBeforeCollectCallback);
+ typedef JsErrorCode (WINAPI *JsrtSetObjectBeforeCollectCallbackPtr)(JsRef ref, void* callbackState, JsObjectBeforeCollectCallback objectBeforeCollectCallback);
typedef JsErrorCode (WINAPI *JsrtSetRuntimeMemoryLimitPtr)(JsRuntimeHandle runtime, size_t memoryLimit);
typedef JsErrorCode (WINAPI *JsrtSetCurrentContextPtr)(JsContextRef context);
typedef JsErrorCode (WINAPI *JsrtGetCurrentContextPtr)(JsContextRef* context);
@@ -16,6 +16,7 @@ struct JsAPIHooks
typedef JsErrorCode (WINAPI *JsrtCreateObjectPtr)(JsValueRef *object);
typedef JsErrorCode (WINAPI *JsrtCreateExternalObjectPtr)(void* data, JsFinalizeCallback callback, JsValueRef *object);
typedef JsErrorCode (WINAPI *JsrtCreateFunctionPtr)(JsNativeFunction nativeFunction, void *callbackState, JsValueRef *function);
+ typedef JsErrorCode (WINAPI *JsrtCreateEnhancedFunctionPtr)(JsEnhancedNativeFunction nativeFunction, JsValueRef metadata, void *callbackState, JsValueRef *function);
typedef JsErrorCode (WINAPI *JsCreateNamedFunctionPtr)(JsValueRef name, JsNativeFunction nativeFunction, void *callbackState, JsValueRef *function);
typedef JsErrorCode (WINAPI *JsrtSetPropertyPtr)(JsValueRef object, JsPropertyIdRef property, JsValueRef value, bool useStrictRules);
typedef JsErrorCode (WINAPI *JsrtGetGlobalObjectPtr)(JsValueRef *globalObject);
@@ -110,6 +111,7 @@ struct JsAPIHooks
JsrtCreateObjectPtr pfJsrtCreateObject;
JsrtCreateExternalObjectPtr pfJsrtCreateExternalObject;
JsrtCreateFunctionPtr pfJsrtCreateFunction;
+ JsrtCreateEnhancedFunctionPtr pfJsrtCreateEnhancedFunction;
JsCreateNamedFunctionPtr pfJsrtCreateNamedFunction;
JsrtSetPropertyPtr pfJsrtSetProperty;
JsrtGetGlobalObjectPtr pfJsrtGetGlobalObject;
@@ -196,7 +198,9 @@ struct JsAPIHooks
JsrtTTDReplayExecutionPtr pfJsrtTTDReplayExecution;
};
-LPCSTR GetChakraDllName();
+#ifdef _WIN32
+LPCWSTR GetChakraDllNameW();
+#endif
class ChakraRTInterface
{
@@ -316,6 +320,7 @@ class ChakraRTInterface
static JsErrorCode WINAPI JsCreateObject(JsValueRef *object) { return HOOK_JS_API(CreateObject(object)); }
static JsErrorCode WINAPI JsCreateExternalObject(void *data, JsFinalizeCallback callback, JsValueRef *object) { return HOOK_JS_API(CreateExternalObject(data, callback, object)); }
static JsErrorCode WINAPI JsCreateFunction(JsNativeFunction nativeFunction, void *callbackState, JsValueRef *function) { return HOOK_JS_API(CreateFunction(nativeFunction, callbackState, function)); }
+ static JsErrorCode WINAPI JsCreateEnhancedFunction(JsEnhancedNativeFunction nativeFunction, JsValueRef metadata, void *callbackState, JsValueRef *function) { return HOOK_JS_API(CreateEnhancedFunction(nativeFunction, metadata, callbackState, function)); }
static JsErrorCode WINAPI JsCreateNamedFunction(JsValueRef name, JsNativeFunction nativeFunction, void *callbackState, JsValueRef *function) { return HOOK_JS_API(CreateNamedFunction(name, nativeFunction, callbackState, function)); }
static JsErrorCode WINAPI JsSetProperty(JsValueRef object, JsPropertyIdRef property, JsValueRef value, bool useStrictRules) { return HOOK_JS_API(SetProperty(object, property, value, useStrictRules)); }
static JsErrorCode WINAPI JsGetGlobalObject(JsValueRef *globalObject) { return HOOK_JS_API(GetGlobalObject(globalObject)); }
diff --git a/deps/chakrashim/core/bin/ch/DbgController.js b/deps/chakrashim/core/bin/ch/DbgController.js
index cdad6e435d4..55c55d68a52 100644
--- a/deps/chakrashim/core/bin/ch/DbgController.js
+++ b/deps/chakrashim/core/bin/ch/DbgController.js
@@ -781,6 +781,44 @@ var controllerObj = (function () {
'sources': sources
});
},
+ dumpFunctionProperties: function (frameIdOrArrayOfIds = [0], expandLevel = 0) {
+ if (typeof frameIdOrArrayOfIds != "number" && !(frameIdOrArrayOfIds instanceof Array)) {
+ frameIdOrArrayOfIds = [0];
+ }
+ if (typeof expandLevel != "number" || expandLevel < 0) {
+ expandLevel = 0;
+ }
+ let stackTrace = callHostFunction(hostDebugObject.JsDiagGetStackTrace);
+ let functionHandles = [];
+ let requestedFrameIndexes = [];
+ if (typeof frameIdOrArrayOfIds === "number") {
+ requestedFrameIndexes.push(frameIdOrArrayOfIds);
+ } else if (frameIdOrArrayOfIds instanceof Array) {
+ frameIdOrArrayOfIds.forEach((s) => {
+ if (typeof s === "number") {
+ requestedFrameIndexes.push(s);
+ }
+ });
+ }
+ if (requestedFrameIndexes.length == 0) {
+ requestedFrameIndexes.push(0);
+ }
+
+ stackTrace.forEach((stackFrame) => {
+ let stackFrameIndex = stackFrame.index;
+ if (requestedFrameIndexes.includes(stackFrameIndex) && !functionHandles.includes(stackFrame.functionHandle)) {
+ functionHandles.push(stackFrame.functionHandle);
+ }
+ });
+
+ let functionProperties = [];
+ functionHandles.forEach((handle) => {
+ functionProperties.push(GetChild({ handle: handle }, expandLevel));
+ });
+ recordEvent({
+ 'functionProperties': functionProperties
+ });
+ },
trace: function (traceFlag) {
_trace |= traceFlag;
}
@@ -925,6 +963,9 @@ function dumpBreak() {
function dumpSourceList() {
controllerObj.pushCommand(controllerObj.debuggerCommands.dumpSourceList, arguments);
}
+function dumpFunctionProperties() {
+ controllerObj.pushCommand(controllerObj.debuggerCommands.dumpFunctionProperties, arguments);
+}
// Start internal tracing. E.g.: /**bp:trace(TRACE_COMMANDS)**/
function trace() {
diff --git a/deps/chakrashim/core/bin/ch/Helpers.cpp b/deps/chakrashim/core/bin/ch/Helpers.cpp
index 1b5108a3a07..a09790a50e3 100644
--- a/deps/chakrashim/core/bin/ch/Helpers.cpp
+++ b/deps/chakrashim/core/bin/ch/Helpers.cpp
@@ -3,34 +3,45 @@
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "stdafx.h"
-
#include
+#define MAX_URI_LENGTH 512
+
//TODO: x-plat definitions
#ifdef _WIN32
-#define MAX_URI_LENGTH 512
+#define TTD_MAX_FILE_LENGTH MAX_PATH
#define TTD_HOST_PATH_SEP "\\"
+#else
+#define TTD_MAX_FILE_LENGTH MAX_URI_LENGTH
+#define TTD_HOST_PATH_SEP "/"
+#endif
void TTDHostBuildCurrentExeDirectory(char* path, size_t* pathLength, size_t bufferLength)
{
- wchar exePath[MAX_PATH];
- GetModuleFileName(NULL, exePath, MAX_PATH);
+ char exePath[TTD_MAX_FILE_LENGTH];
+ PlatformAgnostic::SystemInfo::GetBinaryLocation(exePath, TTD_MAX_FILE_LENGTH);
- size_t i = wcslen(exePath) - 1;
- while(exePath[i] != _u('\\'))
+ size_t i = strlen(exePath) - 1;
+ while (exePath[i] != TTD_HOST_PATH_SEP[0] && i != 0)
{
--i;
}
-
- if(i * 3 > bufferLength)
+ if (i == 0)
{
- printf("Don't overflow path buffer during conversion");
+ fwprintf(stderr, _u("Can't get current exe directory"));
exit(1);
}
- *pathLength = utf8::EncodeInto((LPUTF8)path, exePath, (charcount_t)(i + 1));
+ if (i + 2 > bufferLength)
+ {
+ fwprintf(stderr, _u("Don't overflow path buffer during copy"));
+ exit(1);
+ }
+ memcpy_s(path, bufferLength, exePath, i + 1);
+ *pathLength = i + 1;
path[*pathLength] = '\0';
}
+#ifdef _WIN32
int TTDHostMKDir(const char* path, size_t pathLength)
{
char16 cpath[MAX_PATH];
@@ -38,7 +49,7 @@ int TTDHostMKDir(const char* path, size_t pathLength)
if(MAX_PATH <= pathLength) //<= to account for null terminator
{
- printf("Don't overflow path buffer during conversion");
+ wprintf(_u("Don't overflow path buffer during conversion"));
exit(1);
}
utf8::DecodeUnitsIntoAndNullTerminate(cpath, pathbase, pathbase + pathLength);
@@ -53,7 +64,7 @@ JsTTDStreamHandle TTDHostOpen(size_t pathLength, const char* path, bool isWrite)
if(MAX_PATH <= pathLength) //<= to account for null terminator
{
- printf("Don't overflow path buffer during conversion");
+ wprintf(_u("Don't overflow path buffer during conversion"));
exit(1);
}
utf8::DecodeUnitsIntoAndNullTerminate(wpath, pathbase, pathbase + pathLength);
@@ -67,64 +78,128 @@ JsTTDStreamHandle TTDHostOpen(size_t pathLength, const char* path, bool isWrite)
#define TTDHostRead(buff, size, handle) fread_s(buff, size, 1, size, (FILE*)handle);
#define TTDHostWrite(buff, size, handle) fwrite(buff, 1, size, (FILE*)handle)
#else
+int TTDHostMKDir(const char* path, size_t pathLength)
+{
+ return mkdir(path, 0700);
+}
-#ifdef __APPLE__
-#include
-#else
-#include
+JsTTDStreamHandle TTDHostOpen(size_t pathLength, const char* path, bool isWrite)
+{
+ return (JsTTDStreamHandle)fopen(path, isWrite ? "w+b" : "r+b");
+}
+
+#define TTDHostRead(buff, size, handle) fread(buff, 1, size, (FILE*)handle)
+#define TTDHostWrite(buff, size, handle) fwrite(buff, 1, size, (FILE*)handle)
#endif
-#define MAX_URI_LENGTH 512
-#define TTD_HOST_PATH_SEP "/"
-void TTDHostBuildCurrentExeDirectory(char* path, size_t* pathLength, size_t bufferLength)
+int GetPathNameLocation(LPCSTR filename)
{
- char exePath[MAX_URI_LENGTH];
- //TODO: xplattodo move this logic to PAL
- #ifdef __APPLE__
- uint32_t tmpPathSize = sizeof(exePath);
- _NSGetExecutablePath(exePath, &tmpPathSize);
- size_t i = strlen(exePath) - 1;
- #else
- size_t i = readlink("/proc/self/exe", exePath, MAX_URI_LENGTH) - 1;
- #endif
+ int filenameLength = (int) strlen(filename);
+ int pos;
- while(exePath[i] != '/')
+ if (filenameLength <= 0)
{
- --i;
+ return -1;
}
- *pathLength = i + 1;
- if(*pathLength > bufferLength)
+ for (pos = filenameLength - 1; pos >= 0; pos--)
{
- printf("Don't overflow path buffer during copy.");
- exit(1);
+ char ch = filename[pos];
+ if (ch == '/' || ch == '\\') break;
}
- memcpy_s(path, bufferLength, exePath, *pathLength);
+ return pos;
}
-int TTDHostMKDir(const char* path, size_t pathLength)
+inline void pathcpy(char * target, LPCSTR src, uint length)
{
- return mkdir(path, 0700);
+#ifndef _WIN32
+ for (int i = 0; i < length; i++)
+ {
+ if (src[i] == '\\')
+ {
+ target[i] = '/';
+ }
+ else
+ {
+ target[i] = src[i];
+ }
+ }
+#else
+ memcpy(target, src, length);
+#endif
}
-JsTTDStreamHandle TTDHostOpen(size_t pathLength, const char* path, bool isWrite)
+uint ConcatPath(LPCSTR filenameLeft, uint posPathSep, LPCSTR filenameRight, char* buffer, uint bufferLength)
{
- return (JsTTDStreamHandle)fopen(path, isWrite ? "w+b" : "r+b");
-}
+ int filenameRightLength = (int) strlen(filenameRight);
-#define TTDHostRead(buff, size, handle) fread(buff, 1, size, (FILE*)handle)
-#define TTDHostWrite(buff, size, handle) fwrite(buff, 1, size, (FILE*)handle)
-#endif
+ // [ path[/] ] + [filename] + /0
+ uint totalLength = posPathSep + filenameRightLength + 1;
+ if (buffer == nullptr)
+ {
+ return totalLength;
+ }
+
+ if (bufferLength < totalLength)
+ {
+ fprintf(stderr, "Error: file path is too long.\n");
+ return (uint)-1;
+ }
-HRESULT Helpers::LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* lengthBytesOut /*= nullptr*/)
+ pathcpy(buffer, filenameLeft, posPathSep);
+ buffer += posPathSep;
+ pathcpy(buffer, filenameRight, filenameRightLength);
+ buffer += filenameRightLength;
+ buffer[0] = char(0);
+ return totalLength;
+}
+
+HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UINT* lengthBytesOut /*= nullptr*/)
{
+ static char sHostApplicationPathBuffer[MAX_URI_LENGTH];
+ static uint sHostApplicationPathBufferLength = (uint) -1;
+ char combinedPathBuffer[MAX_URI_LENGTH];
+
HRESULT hr = S_OK;
BYTE * pRawBytes = nullptr;
UINT lengthBytes = 0;
contents = nullptr;
FILE * file = NULL;
+ LPCSTR filename = filenameToLoad;
+ if (sHostApplicationPathBufferLength == (uint)-1)
+ {
+ // consider incoming filename as the host app and base its' path for others
+ sHostApplicationPathBufferLength = GetPathNameLocation(filename);
+ if (sHostApplicationPathBufferLength == -1)
+ {
+ // host app has no path info. (it must be located on current folder!)
+ sHostApplicationPathBufferLength = 0;
+ }
+ else
+ {
+ sHostApplicationPathBufferLength += 1;
+ Assert(sHostApplicationPathBufferLength < MAX_URI_LENGTH);
+ // save host app's path and fix the path separator for platform
+ pathcpy(sHostApplicationPathBuffer, filename, sHostApplicationPathBufferLength);
+ }
+ sHostApplicationPathBuffer[sHostApplicationPathBufferLength] = char(0);
+ }
+ else if (filename[0] != '/' && filename[0] != '\\') // make sure it's not a full path
+ {
+ // concat host path and filename
+ uint len = ConcatPath(sHostApplicationPathBuffer, sHostApplicationPathBufferLength,
+ filename, combinedPathBuffer, MAX_URI_LENGTH);
+
+ if (len == (uint)-1)
+ {
+ hr = E_FAIL;
+ goto Error;
+ }
+ filename = combinedPathBuffer;
+ }
+
//
// Open the file as a binary file to prevent CRT from handling encoding, line-break conversions,
// etc.
@@ -135,7 +210,7 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* len
{
#ifdef _WIN32
DWORD lastError = GetLastError();
- char16 wszBuff[512];
+ char16 wszBuff[MAX_URI_LENGTH];
fprintf(stderr, "Error in opening file '%s' ", filename);
wszBuff[0] = 0;
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
@@ -191,6 +266,9 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* len
// wrongly classified as ANSI
//
{
+#pragma warning(push)
+// suppressing prefast warning that "readable size is bufferLength bytes but 2 may be read" as bufferLength is clearly > 2 in the code that follows
+#pragma warning(disable:6385)
C_ASSERT(sizeof(WCHAR) == 2);
if (bufferLength > 2)
{
@@ -211,6 +289,7 @@ HRESULT Helpers::LoadScriptFromFile(LPCSTR filename, LPCSTR& contents, UINT* len
#pragma prefast(pop)
}
}
+#pragma warning(pop)
}
contents = reinterpret_cast(pRawBytes);
@@ -336,7 +415,7 @@ HRESULT Helpers::LoadBinaryFile(LPCSTR filename, LPCSTR& contents, UINT& lengthB
fprintf(stderr, "Error in opening file '%s' ", filename);
#ifdef _WIN32
DWORD lastError = GetLastError();
- char16 wszBuff[512];
+ char16 wszBuff[MAX_URI_LENGTH];
wszBuff[0] = 0;
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
nullptr,
@@ -351,7 +430,7 @@ HRESULT Helpers::LoadBinaryFile(LPCSTR filename, LPCSTR& contents, UINT& lengthB
#endif
fprintf(stderr, "\n");
}
- return E_FAIL;
+ return E_FAIL;
}
// file will not be nullptr if _wfopen_s succeeds
__analysis_assume(file != nullptr);
@@ -415,8 +494,8 @@ void Helpers::CreateTTDDirectoryAsNeeded(size_t* uriLength, char* uri, const cha
{
if(*uriLength + strlen(asciiDir1) + wcslen(asciiDir2) + 2 > MAX_URI_LENGTH || strlen(asciiDir1) >= MAX_TTD_ASCII_PATH_EXT_LENGTH || wcslen(asciiDir2) >= MAX_TTD_ASCII_PATH_EXT_LENGTH)
{
- printf("We assume bounded MAX_URI_LENGTH for simplicity.\n");
- printf("%s, %s, %ls\n", uri, asciiDir1, asciiDir2);
+ wprintf(_u("We assume bounded MAX_URI_LENGTH for simplicity.\n"));
+ wprintf(_u("%S, %S, %ls\n"), uri, asciiDir1, asciiDir2);
exit(1);
}
@@ -426,8 +505,8 @@ void Helpers::CreateTTDDirectoryAsNeeded(size_t* uriLength, char* uri, const cha
extLength = sprintf_s(uri + *uriLength, MAX_TTD_ASCII_PATH_EXT_LENGTH, "%s%s", asciiDir1, TTD_HOST_PATH_SEP);
if(extLength == -1 || MAX_URI_LENGTH < (*uriLength) + extLength)
{
- printf("Failed directory extension 1.\n");
- printf("%s, %s, %ls\n", uri, asciiDir1, asciiDir2);
+ wprintf(_u("Failed directory extension 1.\n"));
+ wprintf(_u("%S, %S, %ls\n"), uri, asciiDir1, asciiDir2);
exit(1);
}
*uriLength += extLength;
@@ -445,7 +524,7 @@ void Helpers::CreateTTDDirectoryAsNeeded(size_t* uriLength, char* uri, const cha
{
if(asciiDir2[i] > CHAR_MAX)
{
- printf("Test directory names can only include ascii chars.\n");
+ wprintf(_u("Test directory names can only include ascii chars.\n"));
exit(1);
}
realAsciiDir2[i] = (char)asciiDir2[i];
@@ -454,8 +533,8 @@ void Helpers::CreateTTDDirectoryAsNeeded(size_t* uriLength, char* uri, const cha
extLength = sprintf_s(uri + *uriLength, MAX_TTD_ASCII_PATH_EXT_LENGTH, "%s%s", realAsciiDir2, TTD_HOST_PATH_SEP);
if(extLength == -1 || MAX_URI_LENGTH < *uriLength + extLength)
{
- printf("Failed directory create 2.\n");
- printf("%s, %s, %ls\n", uri, asciiDir1, asciiDir2);
+ wprintf(_u("Failed directory create 2.\n"));
+ wprintf(_u("%S, %S, %ls\n"), uri, asciiDir1, asciiDir2);
exit(1);
}
*uriLength += extLength;
@@ -481,7 +560,7 @@ JsTTDStreamHandle CALLBACK Helpers::TTCreateStreamCallback(size_t uriLength, con
if(uriLength + asciiNameLength + 1 > MAX_URI_LENGTH)
{
- printf("We assume bounded MAX_URI_LENGTH for simplicity.");
+ wprintf(_u("We assume bounded MAX_URI_LENGTH for simplicity."));
exit(1);
}
diff --git a/deps/chakrashim/core/bin/ch/JITProcessManager.cpp b/deps/chakrashim/core/bin/ch/JITProcessManager.cpp
index dbe03f3a94c..e03e9eaa07b 100644
--- a/deps/chakrashim/core/bin/ch/JITProcessManager.cpp
+++ b/deps/chakrashim/core/bin/ch/JITProcessManager.cpp
@@ -68,9 +68,9 @@ HRESULT JITProcessManager::CreateServerProcess(int argc, __in_ecount(argc) LPWST
#pragma warning(suppress: 6386) // buffer overrun
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- hr = StringCchCopyW(cmdLine, cmdLineSize, L"ch.exe -OOPCFGRegistration- -CheckOpHelpers -jitserver:");
+ hr = StringCchCopyW(cmdLine, cmdLineSize, _u("ch.exe -OOPCFGRegistration- -CheckOpHelpers -jitserver:"));
#else
- hr = StringCchCopyW(cmdLine, cmdLineSize, L"ch.exe -jitserver:");
+ hr = StringCchCopyW(cmdLine, cmdLineSize, _u("ch.exe -jitserver:"));
#endif
if (FAILED(hr))
{
@@ -91,7 +91,7 @@ HRESULT JITProcessManager::CreateServerProcess(int argc, __in_ecount(argc) LPWST
for (int i = 1; i < argc; ++i)
{
- hr = StringCchCatW(cmdLine, cmdLineSize, L" ");
+ hr = StringCchCatW(cmdLine, cmdLineSize, _u(" "));
if (FAILED(hr))
{
return hr;
diff --git a/deps/chakrashim/core/bin/ch/MessageQueue.h b/deps/chakrashim/core/bin/ch/MessageQueue.h
index b75ca48f0f9..bc350806ec8 100644
--- a/deps/chakrashim/core/bin/ch/MessageQueue.h
+++ b/deps/chakrashim/core/bin/ch/MessageQueue.h
@@ -102,6 +102,16 @@ class SortedList
}
}
+ template
+ void RemoveAll(PredicateFn fn)
+ {
+ while (head != nullptr)
+ {
+ fn(head->data);
+ Remove(head);
+ }
+ }
+
bool IsEmpty()
{
return head == nullptr;
@@ -229,10 +239,9 @@ class MessageQueue
void RemoveAll()
{
- m_queue.Remove([](const ListEntry& entry) {
+ m_queue.RemoveAll([](const ListEntry& entry) {
MessageBase* msg = entry.message;
delete msg;
- return true;
});
}
diff --git a/deps/chakrashim/core/bin/ch/WScriptJsrt.cpp b/deps/chakrashim/core/bin/ch/WScriptJsrt.cpp
index 1af1b2a36d1..c34f1090658 100644
--- a/deps/chakrashim/core/bin/ch/WScriptJsrt.cpp
+++ b/deps/chakrashim/core/bin/ch/WScriptJsrt.cpp
@@ -70,8 +70,7 @@ DWORD_PTR WScriptJsrt::GetNextSourceContext()
void WScriptJsrt::RegisterScriptDir(DWORD_PTR sourceContext, LPCSTR fullDirNarrow)
{
- char dir[_MAX_PATH];
- scriptDirMap[sourceContext] = std::string(GetDir(fullDirNarrow, dir));
+ GetDir(fullDirNarrow, &scriptDirMap[sourceContext]);
}
bool WScriptJsrt::CreateArgumentsObject(JsValueRef *argsObject)
@@ -206,7 +205,7 @@ JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *argu
}
else
{
- returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree);
+ returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, true);
}
}
}
@@ -259,6 +258,7 @@ JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall
AutoString fileName;
AutoString scriptInjectType;
char fileNameBuffer[MAX_PATH];
+ bool isFile = true;
IfJsrtErrorSetGo(fileContent.Initialize(arguments[1]));
// ExternalArrayBuffer Finalize will clean this up
@@ -276,17 +276,21 @@ JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall
}
}
- if (!fileNameNarrow && isSourceModule)
+ if (!fileNameNarrow)
{
- sprintf_s(fileNameBuffer, MAX_PATH, "moduleScript%i.js", (int)sourceContext);
- fileNameNarrow = fileNameBuffer;
+ isFile = false;
+ if (isSourceModule)
+ {
+ sprintf_s(fileNameBuffer, MAX_PATH, "moduleScript%i.js", (int)sourceContext);
+ fileNameNarrow = fileNameBuffer;
+ }
}
if (*fileContent)
{
// TODO: This is CESU-8. How to tell the engine?
// TODO: How to handle this source (script) life time?
- returnValue = LoadScript(callee, fileNameNarrow, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree);
+ returnValue = LoadScript(callee, fileNameNarrow, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, isFile);
}
}
@@ -333,15 +337,22 @@ JsErrorCode WScriptJsrt::InitializeModuleInfo(JsValueRef specifier, JsModuleReco
return JsNoError;
}
-char* WScriptJsrt::GetDir(LPCSTR fullPathNarrow, __out_ecount(260) char* const fullDirNarrow)
+void WScriptJsrt::GetDir(LPCSTR fullPathNarrow, std::string *fullDirNarrow)
{
- char dir[_MAX_DIR];
- _splitpath_s(fullPathNarrow, fullDirNarrow, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
- strcat_s(fullDirNarrow, _MAX_PATH, dir);
- return fullDirNarrow;
+ char fileDrive[_MAX_DRIVE];
+ char fileDir[_MAX_DIR];
+
+ std::string result;
+ if (_splitpath_s(fullPathNarrow, fileDrive, _countof(fileDrive), fileDir, _countof(fileDir), nullptr, 0, nullptr, 0) == 0)
+ {
+ result += fileDrive;
+ result += fileDir;
+ }
+
+ *fullDirNarrow = result;
}
-JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName)
+JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName, bool isFile)
{
DWORD_PTR dwSourceCookie = WScriptJsrt::GetNextSourceContext();
JsModuleRecord requestModule = JS_INVALID_REFERENCE;
@@ -369,8 +380,7 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
{
if (fullName)
{
- char dir[_MAX_PATH];
- moduleDirMap[requestModule] = std::string(GetDir(fullName, dir));
+ GetDir(fullName, &moduleDirMap[requestModule]);
}
moduleRecordMap[std::string(moduleRecordKey)] = requestModule;
@@ -385,6 +395,15 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
// ParseModuleSource is sync, while additional fetch & evaluation are async.
unsigned int fileContentLength = (fileContent == nullptr) ? 0 : (unsigned int)strlen(fileContent);
+
+ if (isFile && fullName)
+ {
+ JsValueRef moduleUrl;
+ ChakraRTInterface::JsCreateString(fullName, strlen(fullName), &moduleUrl);
+ errorCode = ChakraRTInterface::JsSetModuleHostInfo(requestModule, JsModuleHostInfo_Url, moduleUrl);
+ IfJsrtErrorFail(errorCode, errorCode);
+ }
+
errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
fileContentLength, JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode)
@@ -397,7 +416,7 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
- LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback)
+ LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback, bool isFile)
{
HRESULT hr = E_FAIL;
JsErrorCode errorCode = JsNoError;
@@ -414,7 +433,7 @@ JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
if (fileName == nullptr)
- {
+ {
fileName = "script.js";
}
@@ -427,7 +446,7 @@ JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
// treated as a module source text instead of opening a new file.
if (isSourceModule || (strcmp(scriptInjectType, "module") == 0))
{
- errorCode = LoadModuleFromString(fileName, fileContent, fullPath);
+ errorCode = LoadModuleFromString(fileName, fileContent, fullPath, isFile);
}
else if (strcmp(scriptInjectType, "self") == 0)
{
@@ -802,7 +821,10 @@ bool WScriptJsrt::InstallObjectsOnObject(JsValueRef object, const char* name,
JsValueRef propertyValueRef;
JsPropertyIdRef propertyId;
IfJsrtErrorFail(CreatePropertyIdFromString(name, &propertyId), false);
- CreateNamedFunction(name, nativeFunction, &propertyValueRef);
+ if (!CreateNamedFunction(name, nativeFunction, &propertyValueRef))
+ {
+ return false;
+ }
IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(object, propertyId,
propertyValueRef, true), false);
return true;
@@ -981,7 +1003,7 @@ JsErrorCode WScriptJsrt::InitializeModuleCallbacks()
bool WScriptJsrt::Uninitialize()
{
- // moduleRecordMap is a global std::map, its destructor may access overrided
+ // moduleRecordMap is a global std::map, its destructor may access overridden
// "operator delete" / global HeapAllocator::Instance. Clear it manually here
// to avoid worrying about global destructor order.
moduleRecordMap.clear();
@@ -1343,7 +1365,7 @@ bool WScriptJsrt::PrintException(LPCSTR fileName, JsErrorCode jsErrorCode)
int line;
int column;
-
+
IfJsrtErrorFail(CreatePropertyIdFromString("line", &linePropertyId), false);
IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
@@ -1522,27 +1544,10 @@ HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
{
LPCSTR fileContent = nullptr;
AutoString specifierStr(specifier);
- char fullPath[_MAX_PATH];
errorCode = specifierStr.GetError();
if (errorCode == JsNoError)
{
- std::string specifierFullPath;
- if (this->moduleRecord)
- {
- auto moduleDirEntry = moduleDirMap.find(this->moduleRecord);
- if (moduleDirEntry != moduleDirMap.end())
- {
- specifierFullPath = moduleDirEntry->second;
- }
- }
-
- specifierFullPath += *specifierStr;
- if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
- {
- return JsErrorInvalidArgument;
- }
-
- hr = Helpers::LoadScriptFromFile(fullPath, fileContent);
+ hr = Helpers::LoadScriptFromFile(*specifierStr, fileContent);
if (FAILED(hr))
{
@@ -1551,11 +1556,11 @@ HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
fprintf(stderr, "Couldn't load file.\n");
}
- LoadScript(nullptr, fullPath, nullptr, "module", true, WScriptJsrt::FinalizeFree);
+ LoadScript(nullptr, *specifierStr, nullptr, "module", true, WScriptJsrt::FinalizeFree, false);
}
else
{
- LoadScript(nullptr, fullPath, fileContent, "module", true, WScriptJsrt::FinalizeFree);
+ LoadScript(nullptr, *specifierStr, fileContent, "module", true, WScriptJsrt::FinalizeFree, true);
}
}
}
@@ -1592,8 +1597,7 @@ JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingMod
JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
if (errorCode == JsNoError)
{
- char dir[_MAX_PATH];
- moduleDirMap[moduleRecord] = std::string(GetDir(fullPath, dir));
+ GetDir(fullPath, &moduleDirMap[moduleRecord]);
InitializeModuleInfo(specifier, moduleRecord);
moduleRecordMap[std::string(fullPath)] = moduleRecord;
ModuleMessage* moduleMessage =
@@ -1659,10 +1663,13 @@ JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord refer
if (HostConfigFlags::flags.TraceHostCallbackIsEnabled)
{
- printf("NotifyModuleReadyCallback(exception) %s\n", fileName.GetString());
+ wprintf(_u("NotifyModuleReadyCallback(exception) %S\n"), fileName.GetString());
}
- PrintException(*fileName, JsErrorScriptException);
+ // No need to print - just consume the exception
+ JsValueRef exception;
+ ChakraRTInterface::JsGetAndClearException(&exception);
+ exception; // unused
}
else
{
diff --git a/deps/chakrashim/core/bin/ch/WScriptJsrt.h b/deps/chakrashim/core/bin/ch/WScriptJsrt.h
index 7eadfb55111..49a4d18bf7b 100644
--- a/deps/chakrashim/core/bin/ch/WScriptJsrt.h
+++ b/deps/chakrashim/core/bin/ch/WScriptJsrt.h
@@ -90,7 +90,7 @@ class WScriptJsrt
#endif
static bool PrintException(LPCSTR fileName, JsErrorCode jsErrorCode);
- static JsValueRef LoadScript(JsValueRef callee, LPCSTR fileName, LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback);
+ static JsValueRef LoadScript(JsValueRef callee, LPCSTR fileName, LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback, bool isFile);
static DWORD_PTR GetNextSourceContext();
static JsValueRef LoadScriptFileHelper(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, bool isSourceModule);
static JsValueRef LoadScriptHelper(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState, bool isSourceModule);
@@ -100,7 +100,7 @@ class WScriptJsrt
private:
static bool CreateArgumentsObject(JsValueRef *argsObject);
static bool CreateNamedFunction(const char*, JsNativeFunction callback, JsValueRef* functionVar);
- static char* GetDir(LPCSTR fullPathNarrow, __out_ecount(260) char* const fullDirNarrow);
+ static void GetDir(LPCSTR fullPathNarrow, std::string *fullDirNarrow);
static JsValueRef CALLBACK EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef CALLBACK QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef CALLBACK LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
@@ -114,7 +114,7 @@ class WScriptJsrt
static JsValueRef CALLBACK RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef CALLBACK EmptyCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
- static JsErrorCode CALLBACK LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName = nullptr);
+ static JsErrorCode CALLBACK LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName = nullptr, bool isFile = false);
static JsErrorCode CALLBACK InitializeModuleInfo(JsValueRef specifier, JsModuleRecord moduleRecord);
static JsValueRef CALLBACK LoadBinaryFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
diff --git a/deps/chakrashim/core/bin/ch/ch.cpp b/deps/chakrashim/core/bin/ch/ch.cpp
index ad1743b0bae..808fda59083 100644
--- a/deps/chakrashim/core/bin/ch/ch.cpp
+++ b/deps/chakrashim/core/bin/ch/ch.cpp
@@ -4,10 +4,18 @@
//-------------------------------------------------------------------------------------------------------
#include "stdafx.h"
#include "Core/AtomLockGuids.h"
-#include
#ifdef _WIN32
#include
#include
+#include
+#else
+#include
+#endif
+
+#ifdef __linux__
+#include
+#elif defined(__APPLE__)
+#include
#endif
unsigned int MessageBase::s_messageCount = 0;
@@ -105,27 +113,30 @@ void __stdcall PrintChVersion()
#ifdef _WIN32
void __stdcall PrintChakraCoreVersion()
{
- char filename[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
+ char16 filename[_MAX_PATH];
+ char16 drive[_MAX_DRIVE];
+ char16 dir[_MAX_DIR];
- LPCSTR chakraDllName = GetChakraDllName();
+ LPCWSTR chakraDllName = GetChakraDllNameW();
+ char16 modulename[_MAX_PATH];
+ if (!PlatformAgnostic::SystemInfo::GetBinaryLocation(modulename, _MAX_PATH))
+ {
+ return;
+ }
- char modulename[_MAX_PATH];
- GetModuleFileNameA(NULL, modulename, _MAX_PATH);
- _splitpath_s(modulename, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
- _makepath_s(filename, drive, dir, chakraDllName, nullptr);
+ _wsplitpath_s(modulename, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
+ _wmakepath_s(filename, drive, dir, chakraDllName, nullptr);
UINT size = 0;
LPBYTE lpBuffer = NULL;
- DWORD verSize = GetFileVersionInfoSizeA(filename, NULL);
+ DWORD verSize = GetFileVersionInfoSizeW(filename, NULL);
if (verSize != NULL)
{
LPSTR verData = new char[verSize];
- if (GetFileVersionInfoA(filename, NULL, verSize, verData) &&
- VerQueryValue(verData, _u("\\"), (VOID FAR * FAR *)&lpBuffer, &size) &&
+ if (GetFileVersionInfoW(filename, NULL, verSize, verData) &&
+ VerQueryValueW(verData, _u("\\"), (VOID FAR * FAR *)&lpBuffer, &size) &&
(size != 0))
{
VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
@@ -134,7 +145,7 @@ void __stdcall PrintChakraCoreVersion()
// Doesn't matter if you are on 32 bit or 64 bit,
// DWORD is always 32 bits, so first two revision numbers
// come from dwFileVersionMS, last two come from dwFileVersionLS
- printf("%s version %d.%d.%d.%d\n",
+ wprintf(_u("%s version %d.%d.%d.%d\n"),
chakraDllName,
(verInfo->dwFileVersionMS >> 16) & 0xffff,
(verInfo->dwFileVersionMS >> 0) & 0xffff,
@@ -305,7 +316,7 @@ static bool CHAKRA_CALLBACK DummyJsSerializedScriptLoadUtf8Source(
return true;
}
-HRESULT RunScript(const char* fileName, LPCSTR fileContents, JsFinalizeCallback fileContentsFinalizeCallback, JsValueRef bufferValue, char *fullPath)
+HRESULT RunScript(const char* fileName, LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, JsValueRef bufferValue, char *fullPath)
{
HRESULT hr = S_OK;
MessageQueue * messageQueue = new MessageQueue();
@@ -430,7 +441,7 @@ HRESULT RunScript(const char* fileName, LPCSTR fileContents, JsFinalizeCallback
{
JsValueRef scriptSource;
IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
- (unsigned int)strlen(fileContents),
+ (unsigned int)fileLength,
fileContentsFinalizeCallback, (void*)fileContents, &scriptSource));
#if ENABLE_TTD
if(doTTRecord)
@@ -522,26 +533,58 @@ HRESULT RunScript(const char* fileName, LPCSTR fileContents, JsFinalizeCallback
static HRESULT CreateRuntime(JsRuntimeHandle *runtime)
{
HRESULT hr = E_FAIL;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateRuntime(jsrtAttributes, nullptr, runtime));
#ifndef _WIN32
- // On Posix, malloc may not return NULL even if there is no
- // memory left. However, kernel will send SIGKILL to process
- // in case we use that `not actually available` memory address.
- // (See posix man malloc and OOM)
-
+ // On Posix, malloc optimistically returns a non-null address without
+ // checking if it's actually able to back that allocation in memory
+ // Upon use of that address however, if the address space for that allocation
+ // can't be committed, the process is killed
+ // See the man page for malloc
+ //
+ // In order to avoid having to deal with this, we set the memory limit for the
+ // runtime to the size of the physical memory on the system
+ // TODO:
+ // We could move the following into its own platform agnostic API
+ // but in this case, this is a one-time call thats not applicable
+ // on Windows so decided to leave as is
+ // Additionally, we can probably do better than just limit to the physical memory
+ // size
+
+#if defined(__APPLE__) || defined(__linux__)
size_t memoryLimit;
- if (PlatformAgnostic::SystemInfo::GetTotalRam(&memoryLimit))
+#ifdef __APPLE__
+ int totalRamHW[] = { CTL_HW, HW_MEMSIZE };
+ size_t length = sizeof(memoryLimit);
+ if (sysctl(totalRamHW, 2, &memoryLimit, &length, NULL, 0) == -1)
{
- IfJsErrorFailLog(ChakraRTInterface::JsSetRuntimeMemoryLimit(*runtime, memoryLimit));
+ memoryLimit = 0;
}
+#else
+ struct sysinfo sysInfo;
+ if (sysinfo(&sysInfo) == -1)
+ {
+ memoryLimit = 0;
+ }
+ else
+ {
+ memoryLimit = sysInfo.totalram;
+ }
+#endif // __APPLE__
+#endif // __APPLE__ || __linux
+#endif // !_WIN32
+
+ IfJsErrorFailLog(ChakraRTInterface::JsCreateRuntime(jsrtAttributes, nullptr, runtime));
+
+#ifndef _WIN32
+ IfJsErrorFailLog(ChakraRTInterface::JsSetRuntimeMemoryLimit(*runtime, memoryLimit));
#endif
+
hr = S_OK;
Error:
return hr;
}
-HRESULT CreateAndRunSerializedScript(const char* fileName, LPCSTR fileContents, JsFinalizeCallback fileContentsFinalizeCallback, char *fullPath)
+HRESULT CreateAndRunSerializedScript(const char* fileName, LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, char *fullPath)
{
HRESULT hr = S_OK;
JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
@@ -567,7 +610,7 @@ HRESULT CreateAndRunSerializedScript(const char* fileName, LPCSTR fileContents,
}
// This is our last call to use fileContents, so pass in the finalizeCallback
- IfFailGo(RunScript(fileName, fileContents, fileContentsFinalizeCallback, bufferVal, fullPath));
+ IfFailGo(RunScript(fileName, fileContents, fileLength, fileContentsFinalizeCallback, bufferVal, fullPath));
if(false)
{
@@ -619,7 +662,7 @@ HRESULT ExecuteTest(const char* fileName)
IfJsErrorFailLog(ChakraRTInterface::JsTTDCreateContext(runtime, true, &context));
IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(context));
- IfFailGo(RunScript(fileName, fileContents, WScriptJsrt::FinalizeFree, nullptr, nullptr));
+ IfFailGo(RunScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, nullptr, nullptr));
unsigned int rcount = 0;
IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(nullptr));
@@ -733,11 +776,11 @@ HRESULT ExecuteTest(const char* fileName)
}
else if (HostConfigFlags::flags.SerializedIsEnabled)
{
- CreateAndRunSerializedScript(fileName, fileContents, WScriptJsrt::FinalizeFree, fullPath);
+ CreateAndRunSerializedScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, fullPath);
}
else
{
- IfFailGo(RunScript(fileName, fileContents, WScriptJsrt::FinalizeFree, nullptr, fullPath));
+ IfFailGo(RunScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, nullptr, fullPath));
}
}
Error:
@@ -801,8 +844,8 @@ HRESULT ExecuteTestWithMemoryCheck(char* fileName)
#ifdef _WIN32
bool HandleJITServerFlag(int& argc, _Inout_updates_to_(argc, argc) LPWSTR argv[])
{
- LPCWSTR flag = L"-jitserver:";
- LPCWSTR flagWithoutColon = L"-jitserver";
+ LPCWSTR flag = _u("-jitserver:");
+ LPCWSTR flagWithoutColon = _u("-jitserver");
size_t flagLen = wcslen(flag);
int i = 0;
@@ -810,7 +853,7 @@ bool HandleJITServerFlag(int& argc, _Inout_updates_to_(argc, argc) LPWSTR argv[]
{
if (!_wcsicmp(argv[i], flagWithoutColon))
{
- connectionUuidString = L"";
+ connectionUuidString = _u("");
break;
}
else if (!_wcsnicmp(argv[i], flag, flagLen))
@@ -818,7 +861,7 @@ bool HandleJITServerFlag(int& argc, _Inout_updates_to_(argc, argc) LPWSTR argv[]
connectionUuidString = argv[i] + flagLen;
if (wcslen(connectionUuidString) == 0)
{
- fwprintf(stdout, L"[FAILED]: must pass a UUID to -jitserver:\n");
+ fwprintf(stdout, _u("[FAILED]: must pass a UUID to -jitserver:\n"));
return false;
}
else
@@ -851,7 +894,7 @@ int _cdecl RunJITServer(int argc, __in_ecount(argc) LPWSTR argv[])
if (!success)
{
- wprintf(L"\nDll load failed\n");
+ wprintf(_u("\nDll load failed\n"));
return ERROR_DLL_INIT_FAILED;
}
@@ -866,7 +909,7 @@ int _cdecl RunJITServer(int argc, __in_ecount(argc) LPWSTR argv[])
status = initRpcServer(&connectionUuid, nullptr, nullptr);
if (FAILED(status))
{
- wprintf(L"InitializeJITServer failed by 0x%x\n", status);
+ wprintf(_u("InitializeJITServer failed by 0x%x\n"), status);
goto cleanup;
}
status = 0;
@@ -907,6 +950,17 @@ int _cdecl wmain(int argc, __in_ecount(argc) LPWSTR argv[])
#endif
#ifdef _WIN32
+ // Set the output mode of stdout so we can display non-ASCII characters on the console and redirect to file as UTF-8
+ {
+ int result = _setmode(_fileno(stdout), _O_U8TEXT); // set stdout to UTF-8 mode
+ if (result == -1)
+ {
+ // Failed to set mode. Undefined behavior may result, so exit now.
+ wprintf(_u("Failed to set output stream mode. Exiting...\n"));
+ return EXIT_FAILURE;
+ }
+ }
+
bool runJITServer = HandleJITServerFlag(argc, argv);
#endif
int retval = -1;
@@ -1102,6 +1156,12 @@ int _cdecl wmain(int argc, __in_ecount(argc) LPWSTR argv[])
}
delete[] argv;
argv = nullptr;
+#ifdef NO_SANITIZE_ADDRESS_CHECK
+ pthread_exit(&retval);
+#else
+ return retval;
#endif
+#else
return retval;
+#endif
}
diff --git a/deps/chakrashim/core/bin/ch/stdafx.h b/deps/chakrashim/core/bin/ch/stdafx.h
index 91aa021c13d..0339a5ad300 100644
--- a/deps/chakrashim/core/bin/ch/stdafx.h
+++ b/deps/chakrashim/core/bin/ch/stdafx.h
@@ -24,17 +24,11 @@
#define IfFalseGo(expr) do { if(!(expr)) { hr = E_FAIL; goto Error; } } while(0)
#define IfFalseGoLabel(expr, label) do { if(!(expr)) { hr = E_FAIL; goto label; } } while(0)
-#define WIN32_LEAN_AND_MEAN 1
-
#include "CommonDefines.h"
#include