2017-08-12 16:48:01 +00:00
/*
* Copyright ( C ) 1999 - 2000 Harri Porten ( porten @ kde . org )
2022-10-23 02:55:20 +00:00
* Copyright ( C ) 2004 - 2021 Apple Inc . All rights reserved .
2017-08-12 16:48:01 +00:00
* Copyright ( C ) 2006 Bjoern Graf ( bjoern . graf @ gmail . com )
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public License
* along with this library ; see the file COPYING . LIB . If not , write to
* the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
* Boston , MA 02110 - 1301 , USA .
*
*/
# include "config.h"
# include "ArrayBuffer.h"
2022-10-23 02:55:20 +00:00
# include "BigIntConstructor.h"
2020-08-29 13:27:11 +00:00
# include "BytecodeCacheError.h"
2018-01-03 05:16:05 +00:00
# include "CatchScope.h"
2017-08-12 16:48:01 +00:00
# include "CodeBlock.h"
2020-08-29 13:27:11 +00:00
# include "CodeCache.h"
2022-10-23 02:55:20 +00:00
# include "CompilerTimingScope.h"
2017-08-12 16:48:01 +00:00
# include "Completion.h"
2018-01-03 05:16:05 +00:00
# include "ConfigFile.h"
2022-10-23 02:55:20 +00:00
# include "DeferredWorkTimer.h"
2017-08-12 16:48:01 +00:00
# include "Disassembler.h"
# include "Exception.h"
# include "ExceptionHelpers.h"
# include "HeapSnapshotBuilder.h"
# include "InitializeThreading.h"
# include "Interpreter.h"
# include "JIT.h"
2022-10-23 02:55:20 +00:00
# include "JITOperationList.h"
2017-08-12 16:48:01 +00:00
# include "JSArray.h"
# include "JSArrayBuffer.h"
2020-08-29 13:27:11 +00:00
# include "JSBigInt.h"
2022-10-23 02:55:20 +00:00
# include "JSFinalizationRegistry.h"
2017-08-12 16:48:01 +00:00
# include "JSFunction.h"
# include "JSInternalPromise.h"
# include "JSLock.h"
# include "JSNativeStdFunction.h"
# include "JSONObject.h"
2022-10-23 02:55:20 +00:00
# include "JSObjectInlines.h"
2018-01-03 05:16:05 +00:00
# include "JSSourceCode.h"
2017-08-12 16:48:01 +00:00
# include "JSString.h"
# include "JSTypedArrays.h"
2018-01-03 05:16:05 +00:00
# include "JSWebAssemblyInstance.h"
# include "JSWebAssemblyMemory.h"
2017-08-12 16:48:01 +00:00
# include "LLIntThunks.h"
# include "ObjectConstructor.h"
# include "ParserError.h"
# include "ProfilerDatabase.h"
# include "ReleaseHeapAccessScope.h"
# include "SamplingProfiler.h"
2022-10-23 02:55:20 +00:00
# include "SimpleTypedArrayController.h"
2017-08-12 16:48:01 +00:00
# include "StackVisitor.h"
# include "StructureInlines.h"
# include "SuperSampler.h"
# include "TestRunnerUtils.h"
2020-08-29 13:27:11 +00:00
# include "TypedArrayInlines.h"
2022-10-23 02:55:20 +00:00
# include "VMInspector.h"
2020-08-29 13:27:11 +00:00
# include "WasmCapabilities.h"
2018-01-03 05:16:05 +00:00
# include "WasmFaultSignalHandler.h"
2017-08-12 16:48:01 +00:00
# include "WasmMemory.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2020-08-29 13:27:11 +00:00
# include <sys/stat.h>
# include <sys/types.h>
2017-08-12 16:48:01 +00:00
# include <type_traits>
2022-10-23 02:55:20 +00:00
# include <wtf/CPUTime.h>
# include <wtf/FileSystem.h>
2017-08-12 16:48:01 +00:00
# include <wtf/MainThread.h>
2020-08-29 13:27:11 +00:00
# include <wtf/MemoryPressureHandler.h>
# include <wtf/MonotonicTime.h>
# include <wtf/Scope.h>
2017-08-12 16:48:01 +00:00
# include <wtf/StringPrintStream.h>
2020-08-29 13:27:11 +00:00
# include <wtf/URL.h>
# include <wtf/WallTime.h>
2017-08-12 16:48:01 +00:00
# include <wtf/text/StringBuilder.h>
2022-10-23 02:55:20 +00:00
# include <wtf/threads/Signals.h>
2017-08-12 16:48:01 +00:00
# if OS(WINDOWS)
# include <direct.h>
2020-08-29 13:27:11 +00:00
# include <fcntl.h>
# include <io.h>
2017-08-12 16:48:01 +00:00
# else
# include <unistd.h>
# endif
2020-08-29 13:27:11 +00:00
# if PLATFORM(COCOA)
# include <crt_externs.h>
# endif
2022-10-23 02:55:20 +00:00
# if PLATFORM(GTK)
# include <locale.h>
# endif
2017-08-12 16:48:01 +00:00
# if HAVE(READLINE)
// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
// We #define it to something else to avoid this conflict.
# define Function ReadlineFunction
# include <readline/history.h>
# include <readline/readline.h>
# undef Function
# endif
# if COMPILER(MSVC)
# include <crtdbg.h>
# include <mmsystem.h>
# include <windows.h>
# endif
2022-10-23 02:55:20 +00:00
# if OS(DARWIN) && CPU(ARM_THUMB2)
2017-08-12 16:48:01 +00:00
# include <fenv.h>
# include <arm/arch.h>
# endif
2022-10-23 02:55:20 +00:00
# if OS(DARWIN)
# include <wtf/spi/darwin/ProcessMemoryFootprint.h>
# elif OS(LINUX)
# include <wtf/linux/ProcessMemoryFootprint.h>
# endif
# if OS(DARWIN) || OS(LINUX)
struct MemoryFootprint : ProcessMemoryFootprint {
MemoryFootprint ( const ProcessMemoryFootprint & src )
: ProcessMemoryFootprint ( src )
{
}
} ;
2020-08-29 13:27:11 +00:00
# else
struct MemoryFootprint {
uint64_t current ;
uint64_t peak ;
2022-10-23 02:55:20 +00:00
2020-08-29 13:27:11 +00:00
static MemoryFootprint now ( )
{
return { 0L , 0L } ;
}
static void resetPeak ( )
{
}
} ;
# endif
2017-08-12 16:48:01 +00:00
# if !defined(PATH_MAX)
# define PATH_MAX 4096
# endif
using namespace JSC ;
namespace {
2022-10-23 02:55:20 +00:00
# define EXIT_EXCEPTION 3
2017-08-12 16:48:01 +00:00
NO_RETURN_WITH_VALUE static void jscExit ( int status )
{
waitForAsynchronousDisassembly ( ) ;
# if ENABLE(DFG_JIT)
if ( DFG : : isCrashing ( ) ) {
for ( ; ; ) {
# if OS(WINDOWS)
Sleep ( 1000 ) ;
# else
pause ( ) ;
# endif
}
}
# endif // ENABLE(DFG_JIT)
exit ( status ) ;
}
2018-01-03 05:16:05 +00:00
static unsigned asyncTestPasses { 0 } ;
static unsigned asyncTestExpectedPasses { 0 } ;
2017-08-12 16:48:01 +00:00
}
2020-08-29 13:27:11 +00:00
template < typename Vector >
static bool fillBufferWithContentsOfFile ( const String & fileName , Vector & buffer ) ;
static RefPtr < Uint8Array > fillBufferWithContentsOfFile ( const String & fileName ) ;
2017-08-12 16:48:01 +00:00
class CommandLine ;
class GlobalObject ;
class Workers ;
template < typename Func >
2020-08-29 13:27:11 +00:00
int runJSC ( const CommandLine & , bool isWorker , const Func & ) ;
2022-10-23 02:55:20 +00:00
static void checkException ( GlobalObject * , bool isLastFile , bool hasException , JSValue , const CommandLine & , bool & success ) ;
2017-08-12 16:48:01 +00:00
class Message : public ThreadSafeRefCounted < Message > {
public :
2022-10-23 02:55:20 +00:00
# if ENABLE(WEBASSEMBLY)
using Content = Variant < ArrayBufferContents , Ref < Wasm : : MemoryHandle > > ;
# else
using Content = Variant < ArrayBufferContents > ;
# endif
Message ( Content & & , int32_t ) ;
2017-08-12 16:48:01 +00:00
~ Message ( ) ;
2022-10-23 02:55:20 +00:00
Content & & releaseContents ( ) { return WTFMove ( m_contents ) ; }
2017-08-12 16:48:01 +00:00
int32_t index ( ) const { return m_index ; }
private :
2022-10-23 02:55:20 +00:00
Content m_contents ;
2017-08-12 16:48:01 +00:00
int32_t m_index { 0 } ;
} ;
class Worker : public BasicRawSentinelNode < Worker > {
public :
Worker ( Workers & ) ;
~ Worker ( ) ;
void enqueue ( const AbstractLocker & , RefPtr < Message > ) ;
RefPtr < Message > dequeue ( ) ;
static Worker & current ( ) ;
private :
static ThreadSpecific < Worker * > & currentWorker ( ) ;
Workers & m_workers ;
Deque < RefPtr < Message > > m_messages ;
} ;
class Workers {
2020-08-29 13:27:11 +00:00
WTF_MAKE_FAST_ALLOCATED ;
WTF_MAKE_NONCOPYABLE ( Workers ) ;
2017-08-12 16:48:01 +00:00
public :
Workers ( ) ;
~ Workers ( ) ;
template < typename Func >
void broadcast ( const Func & ) ;
2020-08-29 13:27:11 +00:00
void report ( const String & ) ;
2017-08-12 16:48:01 +00:00
String tryGetReport ( ) ;
String getReport ( ) ;
static Workers & singleton ( ) ;
private :
friend class Worker ;
Lock m_lock ;
Condition m_condition ;
SentinelLinkedList < Worker , BasicRawSentinelNode < Worker > > m_workers ;
Deque < String > m_reports ;
} ;
2020-08-29 13:27:11 +00:00
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionCreateGlobalObject ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCreateHeapBigInt ) ;
# if USE(BIGINT32)
static JSC_DECLARE_HOST_FUNCTION ( functionCreateBigInt32 ) ;
# endif
static JSC_DECLARE_HOST_FUNCTION ( functionUseBigInt32 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIsBigInt32 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIsHeapBigInt ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionPrintStdOut ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionPrintStdErr ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDebug ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDescribe ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDescribeArray ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionSleepSeconds ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionJSCStack ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionGCAndSweep ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFullGC ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionEdenGC ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionHeapSize ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCreateMemoryFootprint ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionResetMemoryPeak ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionAddressOf ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionVersion ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionRun ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionRunString ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionLoad ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionLoadString ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionReadFile ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCheckSyntax ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionReadline ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionPreciseTime ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionNeverInlineFunction ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionNoDFG ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionNoFTL ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionNoOSRExitFuzzing ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionOptimizeNextInvocation ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionNumberOfDFGCompiles ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCallerIsOMGCompiled ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionJSCOptions ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionReoptimizationRetryCount ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionTransferArrayBuffer ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFailNextNewCodeBlock ) ;
static NO_RETURN_WITH_VALUE JSC_DECLARE_HOST_FUNCTION ( functionQuit ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFalse ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionUndefined1 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionUndefined2 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIsInt32 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIsPureNaN ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionEffectful42 ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIdentity ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionMakeMasquerader ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCallMasquerader ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionHasCustomProperties ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDumpTypesForAllVariables ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDrainMicrotasks ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionSetTimeout ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionReleaseWeakRefs ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFinalizationRegistryLiveCount ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFinalizationRegistryDeadCount ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIs32BitPlatform ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCheckModuleSyntax ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionPlatformSupportsSamplingProfiler ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionGenerateHeapSnapshot ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionGenerateHeapSnapshotForGCDebugging ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionResetSuperSamplerState ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionEnsureArrayStorage ) ;
2017-08-12 16:48:01 +00:00
# if ENABLE(SAMPLING_PROFILER)
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionStartSamplingProfiler ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionSamplingProfilerStackTraces ) ;
2017-08-12 16:48:01 +00:00
# endif
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionMaxArguments ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionAsyncTestStart ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionAsyncTestPassed ) ;
2017-08-12 16:48:01 +00:00
# if ENABLE(WEBASSEMBLY)
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionWebAssemblyMemoryMode ) ;
2017-08-12 16:48:01 +00:00
# endif
# if ENABLE(SAMPLING_FLAGS)
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionSetSamplingFlags ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionClearSamplingFlags ) ;
2017-08-12 16:48:01 +00:00
# endif
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_HOST_FUNCTION ( functionGetRandomSeed ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionSetRandomSeed ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionIsRope ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionCallerSourceOrigin ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarCreateRealm ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarEvalScript ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentStart ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentReceiveBroadcast ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentReport ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentSleep ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentBroadcast ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentGetReport ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentLeaving ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDollarAgentMonotonicNow ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionWaitForReport ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionHeapCapacity ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionFlashHeapAccess ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDisableRichSourceInfo ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionMallocInALoop ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionTotalCompileTime ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionSetUnhandledRejectionCallback ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionAsDoubleNumber ) ;
static JSC_DECLARE_HOST_FUNCTION ( functionDropAllLocks ) ;
2017-08-12 16:48:01 +00:00
struct Script {
enum class StrictMode {
Strict ,
Sloppy
} ;
enum class ScriptType {
Script ,
Module
} ;
enum class CodeSource {
File ,
CommandLine
} ;
StrictMode strictMode ;
CodeSource codeSource ;
ScriptType scriptType ;
char * argument ;
Script ( StrictMode strictMode , CodeSource codeSource , ScriptType scriptType , char * argument )
: strictMode ( strictMode )
, codeSource ( codeSource )
, scriptType ( scriptType )
, argument ( argument )
{
if ( strictMode = = StrictMode : : Strict )
ASSERT ( codeSource = = CodeSource : : File ) ;
}
} ;
class CommandLine {
public :
CommandLine ( int argc , char * * argv )
{
parseArguments ( argc , argv ) ;
}
2022-10-23 02:55:20 +00:00
enum CommandLineForWorkersTag { CommandLineForWorkers } ;
CommandLine ( CommandLineForWorkersTag )
{
}
2017-08-12 16:48:01 +00:00
Vector < Script > m_scripts ;
Vector < String > m_arguments ;
String m_profilerOutput ;
String m_uncaughtExceptionName ;
2020-08-29 13:27:11 +00:00
bool m_interactive { false } ;
bool m_dump { false } ;
bool m_module { false } ;
bool m_exitCode { false } ;
bool m_destroyVM { false } ;
bool m_profile { false } ;
2018-01-03 05:16:05 +00:00
bool m_treatWatchdogExceptionAsSuccess { false } ;
2017-08-12 16:48:01 +00:00
bool m_alwaysDumpUncaughtException { false } ;
2020-08-29 13:27:11 +00:00
bool m_dumpMemoryFootprint { false } ;
2017-08-12 16:48:01 +00:00
bool m_dumpSamplingProfilerData { false } ;
bool m_enableRemoteDebugging { false } ;
2022-10-23 02:55:20 +00:00
bool m_canBlockIsFalse { false } ;
2017-08-12 16:48:01 +00:00
void parseArguments ( int , char * * ) ;
} ;
static const char interactivePrompt [ ] = " >>> " ;
class StopWatch {
public :
void start ( ) ;
void stop ( ) ;
long getElapsedMS ( ) ; // call stop() first
private :
2020-08-29 13:27:11 +00:00
MonotonicTime m_startTime ;
MonotonicTime m_stopTime ;
2017-08-12 16:48:01 +00:00
} ;
void StopWatch : : start ( )
{
2020-08-29 13:27:11 +00:00
m_startTime = MonotonicTime : : now ( ) ;
2017-08-12 16:48:01 +00:00
}
void StopWatch : : stop ( )
{
2020-08-29 13:27:11 +00:00
m_stopTime = MonotonicTime : : now ( ) ;
2017-08-12 16:48:01 +00:00
}
long StopWatch : : getElapsedMS ( )
{
2020-08-29 13:27:11 +00:00
return ( m_stopTime - m_startTime ) . millisecondsAs < long > ( ) ;
2017-08-12 16:48:01 +00:00
}
template < typename Vector >
static inline String stringFromUTF ( const Vector & utf8 )
{
return String : : fromUTF8WithLatin1Fallback ( utf8 . data ( ) , utf8 . size ( ) ) ;
}
2022-10-23 02:55:20 +00:00
static JSC_DECLARE_CUSTOM_GETTER ( accessorMakeMasquerader ) ;
static JSC_DECLARE_CUSTOM_SETTER ( testCustomAccessorSetter ) ;
static JSC_DECLARE_CUSTOM_SETTER ( testCustomValueSetter ) ;
JSC_DEFINE_CUSTOM_GETTER ( accessorMakeMasquerader , ( JSGlobalObject * globalObject , EncodedJSValue , PropertyName ) )
{
VM & vm = globalObject - > vm ( ) ;
return JSValue : : encode ( InternalFunction : : createFunctionThatMasqueradesAsUndefined ( vm , globalObject , 0 , " IsHTMLDDA " _s , functionCallMasquerader ) ) ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
class GlobalObject final : public JSGlobalObject {
2017-08-12 16:48:01 +00:00
public :
2022-10-23 02:55:20 +00:00
using Base = JSGlobalObject ;
2017-08-12 16:48:01 +00:00
static GlobalObject * create ( VM & vm , Structure * structure , const Vector < String > & arguments )
{
GlobalObject * object = new ( NotNull , allocateCell < GlobalObject > ( vm . heap ) ) GlobalObject ( vm , structure ) ;
object - > finishCreation ( vm , arguments ) ;
return object ;
}
DECLARE_INFO ;
static const GlobalObjectMethodTable s_globalObjectMethodTable ;
static Structure * createStructure ( VM & vm , JSValue prototype )
{
2022-10-23 02:55:20 +00:00
return Structure : : create ( vm , nullptr , prototype , TypeInfo ( GlobalObjectType , StructureFlags ) , info ( ) ) ;
2017-08-12 16:48:01 +00:00
}
static RuntimeFlags javaScriptRuntimeFlags ( const JSGlobalObject * ) { return RuntimeFlags : : createAllEnabled ( ) ; }
2022-10-23 02:55:20 +00:00
private :
GlobalObject ( VM & , Structure * ) ;
static constexpr unsigned DontEnum = 0 | PropertyAttribute : : DontEnum ;
2017-08-12 16:48:01 +00:00
void finishCreation ( VM & vm , const Vector < String > & arguments )
{
Base : : finishCreation ( vm ) ;
2022-10-23 02:55:20 +00:00
JSC_TO_STRING_TAG_WITHOUT_TRANSITION ( ) ;
2020-08-29 13:27:11 +00:00
2017-08-12 16:48:01 +00:00
addFunction ( vm , " debug " , functionDebug , 1 ) ;
addFunction ( vm , " describe " , functionDescribe , 1 ) ;
addFunction ( vm , " describeArray " , functionDescribeArray , 1 ) ;
addFunction ( vm , " print " , functionPrintStdOut , 1 ) ;
addFunction ( vm , " printErr " , functionPrintStdErr , 1 ) ;
addFunction ( vm , " quit " , functionQuit , 0 ) ;
addFunction ( vm , " gc " , functionGCAndSweep , 0 ) ;
addFunction ( vm , " fullGC " , functionFullGC , 0 ) ;
addFunction ( vm , " edenGC " , functionEdenGC , 0 ) ;
addFunction ( vm , " gcHeapSize " , functionHeapSize , 0 ) ;
2020-08-29 13:27:11 +00:00
addFunction ( vm , " MemoryFootprint " , functionCreateMemoryFootprint , 0 ) ;
addFunction ( vm , " resetMemoryPeak " , functionResetMemoryPeak , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " addressOf " , functionAddressOf , 1 ) ;
addFunction ( vm , " version " , functionVersion , 1 ) ;
addFunction ( vm , " run " , functionRun , 1 ) ;
addFunction ( vm , " runString " , functionRunString , 1 ) ;
addFunction ( vm , " load " , functionLoad , 1 ) ;
addFunction ( vm , " loadString " , functionLoadString , 1 ) ;
addFunction ( vm , " readFile " , functionReadFile , 2 ) ;
addFunction ( vm , " read " , functionReadFile , 2 ) ;
addFunction ( vm , " checkSyntax " , functionCheckSyntax , 1 ) ;
addFunction ( vm , " sleepSeconds " , functionSleepSeconds , 1 ) ;
addFunction ( vm , " jscStack " , functionJSCStack , 1 ) ;
addFunction ( vm , " readline " , functionReadline , 0 ) ;
addFunction ( vm , " preciseTime " , functionPreciseTime , 0 ) ;
addFunction ( vm , " neverInlineFunction " , functionNeverInlineFunction , 1 ) ;
addFunction ( vm , " noInline " , functionNeverInlineFunction , 1 ) ;
addFunction ( vm , " noDFG " , functionNoDFG , 1 ) ;
addFunction ( vm , " noFTL " , functionNoFTL , 1 ) ;
addFunction ( vm , " noOSRExitFuzzing " , functionNoOSRExitFuzzing , 1 ) ;
addFunction ( vm , " numberOfDFGCompiles " , functionNumberOfDFGCompiles , 1 ) ;
2022-10-23 02:55:20 +00:00
addFunction ( vm , " callerIsOMGCompiled " , functionCallerIsOMGCompiled , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " jscOptions " , functionJSCOptions , 0 ) ;
addFunction ( vm , " optimizeNextInvocation " , functionOptimizeNextInvocation , 1 ) ;
addFunction ( vm , " reoptimizationRetryCount " , functionReoptimizationRetryCount , 1 ) ;
addFunction ( vm , " transferArrayBuffer " , functionTransferArrayBuffer , 1 ) ;
addFunction ( vm , " failNextNewCodeBlock " , functionFailNextNewCodeBlock , 1 ) ;
# if ENABLE(SAMPLING_FLAGS)
addFunction ( vm , " setSamplingFlags " , functionSetSamplingFlags , 1 ) ;
addFunction ( vm , " clearSamplingFlags " , functionClearSamplingFlags , 1 ) ;
# endif
2020-08-29 13:27:11 +00:00
2022-10-23 02:55:20 +00:00
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " OSRExit " ) , 0 , functionUndefined1 , OSRExitIntrinsic , DontEnum ) ;
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " isFinalTier " ) , 0 , functionFalse , IsFinalTierIntrinsic , DontEnum ) ;
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " predictInt32 " ) , 0 , functionUndefined2 , SetInt32HeapPredictionIntrinsic , DontEnum ) ;
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " isInt32 " ) , 0 , functionIsInt32 , CheckInt32Intrinsic , DontEnum ) ;
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " isPureNaN " ) , 0 , functionIsPureNaN , CheckInt32Intrinsic , DontEnum ) ;
putDirectNativeFunction ( vm , this , Identifier : : fromString ( vm , " fiatInt52 " ) , 0 , functionIdentity , FiatInt52Intrinsic , DontEnum ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " effectful42 " , functionEffectful42 , 0 ) ;
addFunction ( vm , " makeMasquerader " , functionMakeMasquerader , 0 ) ;
addFunction ( vm , " hasCustomProperties " , functionHasCustomProperties , 0 ) ;
addFunction ( vm , " createGlobalObject " , functionCreateGlobalObject , 0 ) ;
2022-10-23 02:55:20 +00:00
addFunction ( vm , " createHeapBigInt " , functionCreateHeapBigInt , 1 ) ;
# if USE(BIGINT32)
addFunction ( vm , " createBigInt32 " , functionCreateBigInt32 , 1 ) ;
# endif
addFunction ( vm , " useBigInt32 " , functionUseBigInt32 , 0 ) ;
addFunction ( vm , " isBigInt32 " , functionIsBigInt32 , 1 ) ;
addFunction ( vm , " isHeapBigInt " , functionIsHeapBigInt , 1 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " dumpTypesForAllVariables " , functionDumpTypesForAllVariables , 0 ) ;
addFunction ( vm , " drainMicrotasks " , functionDrainMicrotasks , 0 ) ;
2022-10-23 02:55:20 +00:00
addFunction ( vm , " setTimeout " , functionSetTimeout , 2 ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
addFunction ( vm , " releaseWeakRefs " , functionReleaseWeakRefs , 0 ) ;
addFunction ( vm , " finalizationRegistryLiveCount " , functionFinalizationRegistryLiveCount , 0 ) ;
addFunction ( vm , " finalizationRegistryDeadCount " , functionFinalizationRegistryDeadCount , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " getRandomSeed " , functionGetRandomSeed , 0 ) ;
addFunction ( vm , " setRandomSeed " , functionSetRandomSeed , 1 ) ;
addFunction ( vm , " isRope " , functionIsRope , 1 ) ;
2018-01-03 05:16:05 +00:00
addFunction ( vm , " callerSourceOrigin " , functionCallerSourceOrigin , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " is32BitPlatform " , functionIs32BitPlatform , 0 ) ;
addFunction ( vm , " checkModuleSyntax " , functionCheckModuleSyntax , 1 ) ;
addFunction ( vm , " platformSupportsSamplingProfiler " , functionPlatformSupportsSamplingProfiler , 0 ) ;
addFunction ( vm , " generateHeapSnapshot " , functionGenerateHeapSnapshot , 0 ) ;
2020-08-29 13:27:11 +00:00
addFunction ( vm , " generateHeapSnapshotForGCDebugging " , functionGenerateHeapSnapshotForGCDebugging , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " resetSuperSamplerState " , functionResetSuperSamplerState , 0 ) ;
addFunction ( vm , " ensureArrayStorage " , functionEnsureArrayStorage , 0 ) ;
# if ENABLE(SAMPLING_PROFILER)
addFunction ( vm , " startSamplingProfiler " , functionStartSamplingProfiler , 0 ) ;
addFunction ( vm , " samplingProfilerStackTraces " , functionSamplingProfilerStackTraces , 0 ) ;
# endif
addFunction ( vm , " maxArguments " , functionMaxArguments , 0 ) ;
2018-01-03 05:16:05 +00:00
addFunction ( vm , " asyncTestStart " , functionAsyncTestStart , 1 ) ;
addFunction ( vm , " asyncTestPassed " , functionAsyncTestPassed , 1 ) ;
2017-08-12 16:48:01 +00:00
# if ENABLE(WEBASSEMBLY)
2018-01-03 05:16:05 +00:00
addFunction ( vm , " WebAssemblyMemoryMode " , functionWebAssemblyMemoryMode , 1 ) ;
2017-08-12 16:48:01 +00:00
# endif
if ( ! arguments . isEmpty ( ) ) {
2022-10-23 02:55:20 +00:00
JSArray * array = constructEmptyArray ( this , nullptr ) ;
2017-08-12 16:48:01 +00:00
for ( size_t i = 0 ; i < arguments . size ( ) ; + + i )
2022-10-23 02:55:20 +00:00
array - > putDirectIndex ( this , i , jsString ( vm , arguments [ i ] ) ) ;
putDirect ( vm , Identifier : : fromString ( vm , " arguments " ) , array , DontEnum ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
putDirect ( vm , Identifier : : fromString ( vm , " console " ) , jsUndefined ( ) , DontEnum ) ;
2017-08-12 16:48:01 +00:00
Structure * plainObjectStructure = JSFinalObject : : createStructure ( vm , this , objectPrototype ( ) , 0 ) ;
JSObject * dollar = JSFinalObject : : create ( vm , plainObjectStructure ) ;
2022-10-23 02:55:20 +00:00
putDirect ( vm , Identifier : : fromString ( vm , " $ " ) , dollar , DontEnum ) ;
putDirect ( vm , Identifier : : fromString ( vm , " $262 " ) , dollar , DontEnum ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , dollar , " createRealm " , functionDollarCreateRealm , 0 ) ;
2022-10-23 02:55:20 +00:00
addFunction ( vm , dollar , " detachArrayBuffer " , functionTransferArrayBuffer , 1 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , dollar , " evalScript " , functionDollarEvalScript , 1 ) ;
2022-10-23 02:55:20 +00:00
dollar - > putDirect ( vm , Identifier : : fromString ( vm , " global " ) , this , DontEnum ) ;
dollar - > putDirectCustomAccessor ( vm , Identifier : : fromString ( vm , " IsHTMLDDA " ) ,
CustomGetterSetter : : create ( vm , accessorMakeMasquerader , nullptr ) ,
static_cast < unsigned > ( PropertyAttribute : : CustomValue )
) ;
2017-08-12 16:48:01 +00:00
JSObject * agent = JSFinalObject : : create ( vm , plainObjectStructure ) ;
2022-10-23 02:55:20 +00:00
dollar - > putDirect ( vm , Identifier : : fromString ( vm , " agent " ) , agent , DontEnum ) ;
2017-08-12 16:48:01 +00:00
// The test262 INTERPRETING.md document says that some of these functions are just in the main
// thread and some are in the other threads. We just put them in all threads.
addFunction ( vm , agent , " start " , functionDollarAgentStart , 1 ) ;
addFunction ( vm , agent , " receiveBroadcast " , functionDollarAgentReceiveBroadcast , 1 ) ;
addFunction ( vm , agent , " report " , functionDollarAgentReport , 1 ) ;
addFunction ( vm , agent , " sleep " , functionDollarAgentSleep , 1 ) ;
addFunction ( vm , agent , " broadcast " , functionDollarAgentBroadcast , 1 ) ;
addFunction ( vm , agent , " getReport " , functionDollarAgentGetReport , 0 ) ;
addFunction ( vm , agent , " leaving " , functionDollarAgentLeaving , 0 ) ;
2020-08-29 13:27:11 +00:00
addFunction ( vm , agent , " monotonicNow " , functionDollarAgentMonotonicNow , 0 ) ;
2017-08-12 16:48:01 +00:00
addFunction ( vm , " waitForReport " , functionWaitForReport , 0 ) ;
2018-01-03 05:16:05 +00:00
addFunction ( vm , " heapCapacity " , functionHeapCapacity , 0 ) ;
addFunction ( vm , " flashHeapAccess " , functionFlashHeapAccess , 0 ) ;
2020-08-29 13:27:11 +00:00
addFunction ( vm , " disableRichSourceInfo " , functionDisableRichSourceInfo , 0 ) ;
addFunction ( vm , " mallocInALoop " , functionMallocInALoop , 0 ) ;
addFunction ( vm , " totalCompileTime " , functionTotalCompileTime , 0 ) ;
2022-10-23 02:55:20 +00:00
addFunction ( vm , " setUnhandledRejectionCallback " , functionSetUnhandledRejectionCallback , 1 ) ;
addFunction ( vm , " asDoubleNumber " , functionAsDoubleNumber , 1 ) ;
addFunction ( vm , " dropAllLocks " , functionDropAllLocks , 1 ) ;
if ( Options : : exposeCustomSettersOnGlobalObjectForTesting ( ) ) {
{
CustomGetterSetter * custom = CustomGetterSetter : : create ( vm , nullptr , testCustomAccessorSetter ) ;
Identifier identifier = Identifier : : fromString ( vm , " testCustomAccessorSetter " ) ;
this - > putDirectCustomAccessor ( vm , identifier , custom , PropertyAttribute : : DontEnum | PropertyAttribute : : DontDelete | PropertyAttribute : : CustomAccessor ) ;
}
{
CustomGetterSetter * custom = CustomGetterSetter : : create ( vm , nullptr , testCustomValueSetter ) ;
Identifier identifier = Identifier : : fromString ( vm , " testCustomValueSetter " ) ;
this - > putDirectCustomAccessor ( vm , identifier , custom , PropertyAttribute : : DontEnum | PropertyAttribute : : DontDelete | PropertyAttribute : : CustomValue ) ;
}
}
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
public :
static bool testCustomSetterImpl ( JSGlobalObject * lexicalGlobalObject , GlobalObject * thisObject , EncodedJSValue encodedValue , const char * propertyName )
{
VM & vm = lexicalGlobalObject - > vm ( ) ;
Identifier identifier = Identifier : : fromString ( vm , propertyName ) ;
thisObject - > putDirect ( vm , identifier , JSValue : : decode ( encodedValue ) , DontEnum ) ;
return true ;
}
private :
2017-08-12 16:48:01 +00:00
void addFunction ( VM & vm , JSObject * object , const char * name , NativeFunction function , unsigned arguments )
{
2022-10-23 02:55:20 +00:00
Identifier identifier = Identifier : : fromString ( vm , name ) ;
object - > putDirect ( vm , identifier , JSFunction : : create ( vm , this , arguments , identifier . string ( ) , function ) , DontEnum ) ;
2017-08-12 16:48:01 +00:00
}
void addFunction ( VM & vm , const char * name , NativeFunction function , unsigned arguments )
{
addFunction ( vm , this , name , function , arguments ) ;
}
2022-10-23 02:55:20 +00:00
static JSInternalPromise * moduleLoaderImportModule ( JSGlobalObject * , JSModuleLoader * , JSString * , JSValue , const SourceOrigin & ) ;
static Identifier moduleLoaderResolve ( JSGlobalObject * , JSModuleLoader * , JSValue , JSValue , JSValue ) ;
static JSInternalPromise * moduleLoaderFetch ( JSGlobalObject * , JSModuleLoader * , JSValue , JSValue , JSValue ) ;
static JSObject * moduleLoaderCreateImportMetaProperties ( JSGlobalObject * , JSModuleLoader * , JSValue , JSModuleRecord * , JSValue ) ;
static void reportUncaughtExceptionAtEventLoop ( JSGlobalObject * , Exception * ) ;
2017-08-12 16:48:01 +00:00
} ;
2022-10-23 02:55:20 +00:00
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE ( GlobalObject , JSGlobalObject ) ;
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
static bool supportsRichSourceInfo = true ;
static bool shellSupportsRichSourceInfo ( const JSGlobalObject * )
{
return supportsRichSourceInfo ;
}
2018-01-03 05:16:05 +00:00
const ClassInfo GlobalObject : : s_info = { " global " , & JSGlobalObject : : s_info , nullptr , nullptr , CREATE_METHOD_TABLE ( GlobalObject ) } ;
2017-08-12 16:48:01 +00:00
const GlobalObjectMethodTable GlobalObject : : s_globalObjectMethodTable = {
2020-08-29 13:27:11 +00:00
& shellSupportsRichSourceInfo ,
2017-08-12 16:48:01 +00:00
& shouldInterruptScript ,
& javaScriptRuntimeFlags ,
2018-01-03 05:16:05 +00:00
nullptr , // queueTaskToEventLoop
2017-08-12 16:48:01 +00:00
& shouldInterruptScriptBeforeTimeout ,
2018-01-03 05:16:05 +00:00
& moduleLoaderImportModule ,
2017-08-12 16:48:01 +00:00
& moduleLoaderResolve ,
& moduleLoaderFetch ,
2020-08-29 13:27:11 +00:00
& moduleLoaderCreateImportMetaProperties ,
2018-01-03 05:16:05 +00:00
nullptr , // moduleLoaderEvaluate
nullptr , // promiseRejectionTracker
2022-10-23 02:55:20 +00:00
& reportUncaughtExceptionAtEventLoop ,
& currentScriptExecutionOwner ,
& scriptExecutionStatus ,
2018-01-03 05:16:05 +00:00
nullptr , // defaultLanguage
2020-08-29 13:27:11 +00:00
nullptr , // compileStreaming
nullptr , // instantinateStreaming
2017-08-12 16:48:01 +00:00
} ;
GlobalObject : : GlobalObject ( VM & vm , Structure * structure )
: JSGlobalObject ( vm , structure , & s_globalObjectMethodTable )
{
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_CUSTOM_SETTER ( testCustomAccessorSetter , ( JSGlobalObject * lexicalGlobalObject , EncodedJSValue thisValue , EncodedJSValue encodedValue ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = lexicalGlobalObject - > vm ( ) ;
RELEASE_ASSERT ( JSValue : : decode ( thisValue ) . isCell ( ) ) ;
JSCell * thisCell = JSValue : : decode ( thisValue ) . asCell ( ) ;
RELEASE_ASSERT ( thisCell - > type ( ) = = PureForwardingProxyType ) ;
GlobalObject * thisObject = jsDynamicCast < GlobalObject * > ( vm , jsCast < JSProxy * > ( thisCell ) - > target ( ) ) ;
RELEASE_ASSERT ( thisObject ) ;
return GlobalObject : : testCustomSetterImpl ( lexicalGlobalObject , thisObject , encodedValue , " _testCustomAccessorSetter " ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_CUSTOM_SETTER ( testCustomValueSetter , ( JSGlobalObject * lexicalGlobalObject , EncodedJSValue thisValue , EncodedJSValue encodedValue ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = lexicalGlobalObject - > vm ( ) ;
RELEASE_ASSERT ( JSValue : : decode ( thisValue ) . isCell ( ) ) ;
JSCell * thisCell = JSValue : : decode ( thisValue ) . asCell ( ) ;
GlobalObject * thisObject = jsDynamicCast < GlobalObject * > ( vm , thisCell ) ;
RELEASE_ASSERT ( thisObject ) ;
return GlobalObject : : testCustomSetterImpl ( lexicalGlobalObject , thisObject , encodedValue , " _testCustomValueSetter " ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
static UChar pathSeparator ( )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
# if OS(WINDOWS)
return ' \\ ' ;
# else
return ' / ' ;
# endif
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
static URL currentWorkingDirectory ( )
2017-08-12 16:48:01 +00:00
{
# if OS(WINDOWS)
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
// The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
// And other I/O functions taking a path name also truncate it. To avoid this situation,
//
// (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
// (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
//
// In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
DWORD bufferLength = : : GetCurrentDirectoryW ( 0 , nullptr ) ;
if ( ! bufferLength )
2022-10-23 02:55:20 +00:00
return { } ;
2017-08-12 16:48:01 +00:00
// In Windows, wchar_t is the UTF-16LE.
// https://msdn.microsoft.com/en-us/library/dd374081.aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
2020-08-29 13:27:11 +00:00
Vector < wchar_t > buffer ( bufferLength ) ;
DWORD lengthNotIncludingNull = : : GetCurrentDirectoryW ( bufferLength , buffer . data ( ) ) ;
String directoryString ( buffer . data ( ) , lengthNotIncludingNull ) ;
2017-08-12 16:48:01 +00:00
// We don't support network path like \\host\share\<path name>.
if ( directoryString . startsWith ( " \\ \\ " ) )
2022-10-23 02:55:20 +00:00
return { } ;
2017-08-12 16:48:01 +00:00
# else
2020-08-29 13:27:11 +00:00
Vector < char > buffer ( PATH_MAX ) ;
if ( ! getcwd ( buffer . data ( ) , PATH_MAX ) )
2022-10-23 02:55:20 +00:00
return { } ;
2020-08-29 13:27:11 +00:00
String directoryString = String : : fromUTF8 ( buffer . data ( ) ) ;
2017-08-12 16:48:01 +00:00
# endif
if ( directoryString . isEmpty ( ) )
2022-10-23 02:55:20 +00:00
return { } ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
// Add a trailing slash if needed so the URL resolves to a directory and not a file.
if ( directoryString [ directoryString . length ( ) - 1 ] ! = pathSeparator ( ) )
directoryString = makeString ( directoryString , pathSeparator ( ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
return URL : : fileURLWithFileSystemPath ( directoryString ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
static URL absolutePath ( const String & fileName )
2018-01-03 05:16:05 +00:00
{
auto directoryName = currentWorkingDirectory ( ) ;
2022-10-23 02:55:20 +00:00
if ( ! directoryName . isValid ( ) )
return URL : : fileURLWithFileSystemPath ( fileName ) ;
return URL ( directoryName , fileName ) ;
2018-01-03 05:16:05 +00:00
}
2022-10-23 02:55:20 +00:00
JSInternalPromise * GlobalObject : : moduleLoaderImportModule ( JSGlobalObject * globalObject , JSModuleLoader * , JSString * moduleNameValue , JSValue parameters , const SourceOrigin & sourceOrigin )
2018-01-03 05:16:05 +00:00
{
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
auto throwScope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
auto * promise = JSInternalPromise : : create ( vm , globalObject - > internalPromiseStructure ( ) ) ;
2018-01-03 05:16:05 +00:00
2020-08-29 13:27:11 +00:00
auto catchScope = DECLARE_CATCH_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
auto rejectWithError = [ & ] ( JSValue error ) {
promise - > reject ( globalObject , error ) ;
return promise ;
2018-01-03 05:16:05 +00:00
} ;
2022-10-23 02:55:20 +00:00
auto reject = [ & ] ( Exception * exception ) {
if ( UNLIKELY ( isTerminatedExecutionException ( vm , exception ) ) )
return promise ;
JSValue error = exception - > value ( ) ;
catchScope . clearException ( ) ;
return rejectWithError ( error ) ;
} ;
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
auto referrer = sourceOrigin . url ( ) ;
auto specifier = moduleNameValue - > value ( globalObject ) ;
RETURN_IF_EXCEPTION ( throwScope , nullptr ) ;
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( catchScope . exception ( ) ) )
return reject ( catchScope . exception ( ) ) ;
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
if ( ! referrer . isLocalFile ( ) )
return rejectWithError ( createError ( globalObject , makeString ( " Could not resolve the referrer's path ' " , referrer . string ( ) , " ', while trying to resolve module ' " , specifier , " '. " ) ) ) ;
if ( ! specifier . startsWith ( ' / ' ) & & ! specifier . startsWith ( " ./ " ) & & ! specifier . startsWith ( " ../ " ) )
return rejectWithError ( createTypeError ( globalObject , makeString ( " Module specifier, ' " _s , specifier , " ' does not start with \" / \" , \" ./ \" , or \" ../ \" . Referenced from: " _s , referrer . fileSystemPath ( ) ) ) ) ;
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
URL moduleURL ( referrer , specifier ) ;
if ( ! moduleURL . isLocalFile ( ) )
return rejectWithError ( createError ( globalObject , makeString ( " Module url, ' " , moduleURL . string ( ) , " ' does not map to a local file. " ) ) ) ;
auto result = JSC : : importModule ( globalObject , Identifier : : fromString ( vm , moduleURL . string ( ) ) , parameters , jsUndefined ( ) ) ;
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( catchScope . exception ( ) ) )
return reject ( catchScope . exception ( ) ) ;
return result ;
2018-01-03 05:16:05 +00:00
}
2022-10-23 02:55:20 +00:00
Identifier GlobalObject : : moduleLoaderResolve ( JSGlobalObject * globalObject , JSModuleLoader * , JSValue keyValue , JSValue referrerValue , JSValue )
2017-08-12 16:48:01 +00:00
{
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2017-08-12 16:48:01 +00:00
2018-01-03 05:16:05 +00:00
scope . releaseAssertNoException ( ) ;
2022-10-23 02:55:20 +00:00
const Identifier key = keyValue . toPropertyKey ( globalObject ) ;
2020-08-29 13:27:11 +00:00
RETURN_IF_EXCEPTION ( scope , { } ) ;
2017-08-12 16:48:01 +00:00
if ( key . isSymbol ( ) )
2020-08-29 13:27:11 +00:00
return key ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
auto resolvePath = [ & ] ( const URL & directoryURL ) - > Identifier {
String specifier = key . impl ( ) ;
if ( ! specifier . startsWith ( ' / ' ) & & ! specifier . startsWith ( " ./ " ) & & ! specifier . startsWith ( " ../ " ) ) {
throwTypeError ( globalObject , scope , makeString ( " Module specifier, ' " _s , specifier , " ' does not start with \" / \" , \" ./ \" , or \" ../ \" . Referenced from: " _s , directoryURL . fileSystemPath ( ) ) ) ;
2020-08-29 13:27:11 +00:00
return { } ;
}
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
if ( ! directoryURL . isLocalFile ( ) ) {
throwException ( globalObject , scope , createError ( globalObject , makeString ( " Could not resolve the referrer's path: " , directoryURL . string ( ) ) ) ) ;
return { } ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
URL resolvedURL ( directoryURL , specifier ) ;
if ( ! resolvedURL . isValid ( ) ) {
throwException ( globalObject , scope , createError ( globalObject , makeString ( " Resolved module url is not valid: " , resolvedURL . string ( ) ) ) ) ;
2020-08-29 13:27:11 +00:00
return { } ;
}
2022-10-23 02:55:20 +00:00
ASSERT ( resolvedURL . isLocalFile ( ) ) ;
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
return Identifier : : fromString ( vm , resolvedURL . string ( ) ) ;
} ;
if ( referrerValue . isUndefined ( ) )
return resolvePath ( currentWorkingDirectory ( ) ) ;
const Identifier referrer = referrerValue . toPropertyKey ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
if ( referrer . isSymbol ( ) )
return resolvePath ( currentWorkingDirectory ( ) ) ;
// If the referrer exists, we assume that the referrer is the correct file url.
URL url = URL ( { } , referrer . impl ( ) ) ;
ASSERT ( url . isLocalFile ( ) ) ;
return resolvePath ( url ) ;
2017-08-12 16:48:01 +00:00
}
2020-08-29 13:27:11 +00:00
template < typename Vector >
static void convertShebangToJSComment ( Vector & buffer )
2017-08-12 16:48:01 +00:00
{
if ( buffer . size ( ) > = 2 ) {
if ( buffer [ 0 ] = = ' # ' & & buffer [ 1 ] = = ' ! ' )
buffer [ 0 ] = buffer [ 1 ] = ' / ' ;
}
}
2020-08-29 13:27:11 +00:00
static RefPtr < Uint8Array > fillBufferWithContentsOfFile ( FILE * file )
{
if ( fseek ( file , 0 , SEEK_END ) = = - 1 )
return nullptr ;
long bufferCapacity = ftell ( file ) ;
if ( bufferCapacity = = - 1 )
return nullptr ;
if ( fseek ( file , 0 , SEEK_SET ) = = - 1 )
return nullptr ;
auto result = Uint8Array : : tryCreate ( bufferCapacity ) ;
if ( ! result )
return nullptr ;
size_t readSize = fread ( result - > data ( ) , 1 , bufferCapacity , file ) ;
if ( readSize ! = static_cast < size_t > ( bufferCapacity ) )
return nullptr ;
return result ;
}
static RefPtr < Uint8Array > fillBufferWithContentsOfFile ( const String & fileName )
{
FILE * f = fopen ( fileName . utf8 ( ) . data ( ) , " rb " ) ;
if ( ! f ) {
fprintf ( stderr , " Could not open file: %s \n " , fileName . utf8 ( ) . data ( ) ) ;
return nullptr ;
}
RefPtr < Uint8Array > result = fillBufferWithContentsOfFile ( f ) ;
fclose ( f ) ;
return result ;
}
template < typename Vector >
static bool fillBufferWithContentsOfFile ( FILE * file , Vector & buffer )
2017-08-12 16:48:01 +00:00
{
// We might have injected "use strict"; at the top.
size_t initialSize = buffer . size ( ) ;
2020-08-29 13:27:11 +00:00
if ( fseek ( file , 0 , SEEK_END ) = = - 1 )
return false ;
long bufferCapacity = ftell ( file ) ;
if ( bufferCapacity = = - 1 )
return false ;
if ( fseek ( file , 0 , SEEK_SET ) = = - 1 )
return false ;
2017-08-12 16:48:01 +00:00
buffer . resize ( bufferCapacity + initialSize ) ;
size_t readSize = fread ( buffer . data ( ) + initialSize , 1 , buffer . size ( ) , file ) ;
return readSize = = buffer . size ( ) - initialSize ;
}
static bool fillBufferWithContentsOfFile ( const String & fileName , Vector < char > & buffer )
{
FILE * f = fopen ( fileName . utf8 ( ) . data ( ) , " rb " ) ;
if ( ! f ) {
fprintf ( stderr , " Could not open file: %s \n " , fileName . utf8 ( ) . data ( ) ) ;
return false ;
}
bool result = fillBufferWithContentsOfFile ( f , buffer ) ;
fclose ( f ) ;
return result ;
}
static bool fetchScriptFromLocalFileSystem ( const String & fileName , Vector < char > & buffer )
{
if ( ! fillBufferWithContentsOfFile ( fileName , buffer ) )
return false ;
convertShebangToJSComment ( buffer ) ;
return true ;
}
2022-10-23 02:55:20 +00:00
class ShellSourceProvider final : public StringSourceProvider {
2020-08-29 13:27:11 +00:00
public :
2022-10-23 02:55:20 +00:00
static Ref < ShellSourceProvider > create ( const String & source , const SourceOrigin & sourceOrigin , String & & sourceURL , const TextPosition & startPosition , SourceProviderSourceType sourceType )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
return adoptRef ( * new ShellSourceProvider ( source , sourceOrigin , WTFMove ( sourceURL ) , startPosition , sourceType ) ) ;
2020-08-29 13:27:11 +00:00
}
2022-10-23 02:55:20 +00:00
~ ShellSourceProvider ( ) final
2020-08-29 13:27:11 +00:00
{
commitCachedBytecode ( ) ;
}
2022-10-23 02:55:20 +00:00
RefPtr < CachedBytecode > cachedBytecode ( ) const final
2020-08-29 13:27:11 +00:00
{
if ( ! m_cachedBytecode )
loadBytecode ( ) ;
return m_cachedBytecode . copyRef ( ) ;
}
2022-10-23 02:55:20 +00:00
void updateCache ( const UnlinkedFunctionExecutable * executable , const SourceCode & , CodeSpecializationKind kind , const UnlinkedFunctionCodeBlock * codeBlock ) const final
2020-08-29 13:27:11 +00:00
{
if ( ! cacheEnabled ( ) | | ! m_cachedBytecode )
return ;
BytecodeCacheError error ;
2022-10-23 02:55:20 +00:00
RefPtr < CachedBytecode > cachedBytecode = encodeFunctionCodeBlock ( executable - > vm ( ) , codeBlock , error ) ;
2020-08-29 13:27:11 +00:00
if ( cachedBytecode & & ! error . isValid ( ) )
m_cachedBytecode - > addFunctionUpdate ( executable , kind , * cachedBytecode ) ;
}
2022-10-23 02:55:20 +00:00
void cacheBytecode ( const BytecodeCacheGenerator & generator ) const final
2020-08-29 13:27:11 +00:00
{
if ( ! cacheEnabled ( ) )
return ;
if ( ! m_cachedBytecode )
m_cachedBytecode = CachedBytecode : : create ( ) ;
auto update = generator ( ) ;
if ( update )
m_cachedBytecode - > addGlobalUpdate ( * update ) ;
}
2022-10-23 02:55:20 +00:00
void commitCachedBytecode ( ) const final
2020-08-29 13:27:11 +00:00
{
if ( ! cacheEnabled ( ) | | ! m_cachedBytecode | | ! m_cachedBytecode - > hasUpdates ( ) )
return ;
auto clearBytecode = makeScopeExit ( [ & ] {
m_cachedBytecode = nullptr ;
} ) ;
String filename = cachePath ( ) ;
2022-10-23 02:55:20 +00:00
auto fd = FileSystem : : openAndLockFile ( filename , FileSystem : : FileOpenMode : : Write , { FileSystem : : FileLockMode : : Exclusive , FileSystem : : FileLockMode : : Nonblocking } ) ;
if ( ! FileSystem : : isHandleValid ( fd ) )
2020-08-29 13:27:11 +00:00
return ;
auto closeFD = makeScopeExit ( [ & ] {
2022-10-23 02:55:20 +00:00
FileSystem : : unlockAndCloseFile ( fd ) ;
2020-08-29 13:27:11 +00:00
} ) ;
2022-10-23 02:55:20 +00:00
long long fileSize ;
if ( ! FileSystem : : getFileSize ( fd , fileSize ) )
return ;
size_t cacheFileSize ;
if ( ! WTF : : convertSafely ( fileSize , cacheFileSize ) | | cacheFileSize ! = m_cachedBytecode - > size ( ) ) {
2020-08-29 13:27:11 +00:00
// The bytecode cache has already been updated
return ;
}
2022-10-23 02:55:20 +00:00
if ( ! FileSystem : : truncateFile ( fd , m_cachedBytecode - > sizeForUpdate ( ) ) )
2020-08-29 13:27:11 +00:00
return ;
m_cachedBytecode - > commitUpdates ( [ & ] ( off_t offset , const void * data , size_t size ) {
2022-10-23 02:55:20 +00:00
long long result = FileSystem : : seekFile ( fd , offset , FileSystem : : FileSeekOrigin : : Beginning ) ;
2020-08-29 13:27:11 +00:00
ASSERT_UNUSED ( result , result ! = - 1 ) ;
2022-10-23 02:55:20 +00:00
size_t bytesWritten = static_cast < size_t > ( FileSystem : : writeToFile ( fd , static_cast < const char * > ( data ) , size ) ) ;
2020-08-29 13:27:11 +00:00
ASSERT_UNUSED ( bytesWritten , bytesWritten = = size ) ;
} ) ;
}
private :
String cachePath ( ) const
{
if ( ! cacheEnabled ( ) )
return static_cast < const char * > ( nullptr ) ;
const char * cachePath = Options : : diskCachePath ( ) ;
2022-10-23 02:55:20 +00:00
String filename = FileSystem : : encodeForFileName ( FileSystem : : lastComponentOfPathIgnoringTrailingSlash ( sourceOrigin ( ) . url ( ) . fileSystemPath ( ) ) ) ;
return FileSystem : : pathByAppendingComponent ( cachePath , makeString ( source ( ) . toString ( ) . hash ( ) , ' - ' , filename , " .bytecode-cache " ) ) ;
2020-08-29 13:27:11 +00:00
}
void loadBytecode ( ) const
{
if ( ! cacheEnabled ( ) )
return ;
String filename = cachePath ( ) ;
if ( filename . isNull ( ) )
return ;
2022-10-23 02:55:20 +00:00
auto fd = FileSystem : : openAndLockFile ( filename , FileSystem : : FileOpenMode : : Read , { FileSystem : : FileLockMode : : Shared , FileSystem : : FileLockMode : : Nonblocking } ) ;
if ( ! FileSystem : : isHandleValid ( fd ) )
2020-08-29 13:27:11 +00:00
return ;
auto closeFD = makeScopeExit ( [ & ] {
2022-10-23 02:55:20 +00:00
FileSystem : : unlockAndCloseFile ( fd ) ;
2020-08-29 13:27:11 +00:00
} ) ;
2022-10-23 02:55:20 +00:00
bool success ;
FileSystem : : MappedFileData mappedFileData ( fd , FileSystem : : MappedFileMode : : Private , success ) ;
2020-08-29 13:27:11 +00:00
2022-10-23 02:55:20 +00:00
if ( ! success )
2020-08-29 13:27:11 +00:00
return ;
2022-10-23 02:55:20 +00:00
m_cachedBytecode = CachedBytecode : : create ( WTFMove ( mappedFileData ) ) ;
2020-08-29 13:27:11 +00:00
}
2022-10-23 02:55:20 +00:00
ShellSourceProvider ( const String & source , const SourceOrigin & sourceOrigin , String & & sourceURL , const TextPosition & startPosition , SourceProviderSourceType sourceType )
: StringSourceProvider ( source , sourceOrigin , WTFMove ( sourceURL ) , startPosition , sourceType )
2020-08-29 13:27:11 +00:00
{
}
static bool cacheEnabled ( )
{
static bool enabled = ! ! Options : : diskCachePath ( ) ;
return enabled ;
}
mutable RefPtr < CachedBytecode > m_cachedBytecode ;
} ;
2022-10-23 02:55:20 +00:00
static inline SourceCode jscSource ( const String & source , const SourceOrigin & sourceOrigin , String sourceURL = String ( ) , const TextPosition & startPosition = TextPosition ( ) , SourceProviderSourceType sourceType = SourceProviderSourceType : : Program )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
return SourceCode ( ShellSourceProvider : : create ( source , sourceOrigin , WTFMove ( sourceURL ) , startPosition , sourceType ) , startPosition . m_line . oneBasedInt ( ) , startPosition . m_column . oneBasedInt ( ) ) ;
2020-08-29 13:27:11 +00:00
}
template < typename Vector >
static inline SourceCode jscSource ( const Vector & utf8 , const SourceOrigin & sourceOrigin , const String & filename )
{
// FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
String str = stringFromUTF ( utf8 ) ;
2022-10-23 02:55:20 +00:00
return jscSource ( str , sourceOrigin , filename ) ;
2020-08-29 13:27:11 +00:00
}
template < typename Vector >
2022-10-23 02:55:20 +00:00
static bool fetchModuleFromLocalFileSystem ( const URL & fileURL , Vector & buffer )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
String fileName = fileURL . fileSystemPath ( ) ;
2017-08-12 16:48:01 +00:00
# if OS(WINDOWS)
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
// Use long UNC to pass the long path name to the Windows APIs.
2020-08-29 13:27:11 +00:00
auto pathName = makeString ( " \\ \\ ? \\ " , fileName ) . wideCharacters ( ) ;
struct _stat status { } ;
if ( _wstat ( pathName . data ( ) , & status ) )
return false ;
if ( ( status . st_mode & S_IFMT ) ! = S_IFREG )
return false ;
FILE * f = _wfopen ( pathName . data ( ) , L " rb " ) ;
2017-08-12 16:48:01 +00:00
# else
2020-08-29 13:27:11 +00:00
auto pathName = fileName . utf8 ( ) ;
struct stat status { } ;
if ( stat ( pathName . data ( ) , & status ) )
return false ;
if ( ( status . st_mode & S_IFMT ) ! = S_IFREG )
return false ;
FILE * f = fopen ( pathName . data ( ) , " r " ) ;
2017-08-12 16:48:01 +00:00
# endif
if ( ! f ) {
fprintf ( stderr , " Could not open file: %s \n " , fileName . utf8 ( ) . data ( ) ) ;
return false ;
}
bool result = fillBufferWithContentsOfFile ( f , buffer ) ;
if ( result )
convertShebangToJSComment ( buffer ) ;
fclose ( f ) ;
return result ;
}
2022-10-23 02:55:20 +00:00
JSInternalPromise * GlobalObject : : moduleLoaderFetch ( JSGlobalObject * globalObject , JSModuleLoader * , JSValue key , JSValue , JSValue )
2017-08-12 16:48:01 +00:00
{
VM & vm = globalObject - > vm ( ) ;
2022-10-23 02:55:20 +00:00
JSInternalPromise * promise = JSInternalPromise : : create ( vm , globalObject - > internalPromiseStructure ( ) ) ;
2020-08-29 13:27:11 +00:00
auto catchScope = DECLARE_CATCH_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
auto rejectWithError = [ & ] ( JSValue error ) {
promise - > reject ( globalObject , error ) ;
return promise ;
} ;
auto reject = [ & ] ( Exception * exception ) {
if ( UNLIKELY ( isTerminatedExecutionException ( vm , exception ) ) )
return promise ;
JSValue error = exception - > value ( ) ;
2020-08-29 13:27:11 +00:00
catchScope . clearException ( ) ;
2022-10-23 02:55:20 +00:00
return rejectWithError ( error ) ;
2020-08-29 13:27:11 +00:00
} ;
2022-10-23 02:55:20 +00:00
String moduleKey = key . toWTFString ( globalObject ) ;
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( catchScope . exception ( ) ) )
return reject ( catchScope . exception ( ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
URL moduleURL ( { } , moduleKey ) ;
ASSERT ( moduleURL . isLocalFile ( ) ) ;
// Strip the URI from our key so Errors print canonical system paths.
moduleKey = moduleURL . fileSystemPath ( ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
Vector < uint8_t > buffer ;
if ( ! fetchModuleFromLocalFileSystem ( moduleURL , buffer ) )
return rejectWithError ( createError ( globalObject , makeString ( " Could not open file ' " , moduleKey , " '. " ) ) ) ;
2020-08-29 13:27:11 +00:00
# if ENABLE(WEBASSEMBLY)
// FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
if ( buffer . size ( ) > = 4 ) {
if ( buffer [ 0 ] = = ' \0 ' & & buffer [ 1 ] = = ' a ' & & buffer [ 2 ] = = ' s ' & & buffer [ 3 ] = = ' m ' ) {
2022-10-23 02:55:20 +00:00
auto source = SourceCode ( WebAssemblySourceProvider : : create ( WTFMove ( buffer ) , SourceOrigin { moduleURL } , WTFMove ( moduleKey ) ) ) ;
2020-08-29 13:27:11 +00:00
catchScope . releaseAssertNoException ( ) ;
auto sourceCode = JSSourceCode : : create ( vm , WTFMove ( source ) ) ;
catchScope . releaseAssertNoException ( ) ;
2022-10-23 02:55:20 +00:00
promise - > resolve ( globalObject , sourceCode ) ;
return promise ;
2020-08-29 13:27:11 +00:00
}
}
# endif
2022-10-23 02:55:20 +00:00
auto sourceCode = JSSourceCode : : create ( vm , jscSource ( stringFromUTF ( buffer ) , SourceOrigin { moduleURL } , WTFMove ( moduleKey ) , TextPosition ( ) , SourceProviderSourceType : : Module ) ) ;
2020-08-29 13:27:11 +00:00
catchScope . releaseAssertNoException ( ) ;
2022-10-23 02:55:20 +00:00
promise - > resolve ( globalObject , sourceCode ) ;
return promise ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSObject * GlobalObject : : moduleLoaderCreateImportMetaProperties ( JSGlobalObject * globalObject , JSModuleLoader * , JSValue key , JSModuleRecord * , JSValue )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
JSObject * metaProperties = constructEmptyObject ( vm , globalObject - > nullPrototypeObjectStructure ( ) ) ;
2020-08-29 13:27:11 +00:00
RETURN_IF_EXCEPTION ( scope , nullptr ) ;
2022-10-23 02:55:20 +00:00
metaProperties - > putDirect ( vm , Identifier : : fromString ( vm , " filename " ) , key ) ;
2020-08-29 13:27:11 +00:00
RETURN_IF_EXCEPTION ( scope , nullptr ) ;
return metaProperties ;
}
2022-10-23 02:55:20 +00:00
static CString cStringFromViewWithString ( JSGlobalObject * globalObject , ThrowScope & scope , StringViewWithUnderlyingString & viewWithString )
2020-08-29 13:27:11 +00:00
{
Expected < CString , UTF8ConversionError > expectedString = viewWithString . view . tryGetUtf8 ( ) ;
if ( expectedString )
return expectedString . value ( ) ;
switch ( expectedString . error ( ) ) {
case UTF8ConversionError : : OutOfMemory :
2022-10-23 02:55:20 +00:00
throwOutOfMemoryError ( globalObject , scope ) ;
2020-08-29 13:27:11 +00:00
break ;
case UTF8ConversionError : : IllegalSource :
2022-10-23 02:55:20 +00:00
scope . throwException ( globalObject , createError ( globalObject , " Illegal source encountered during UTF8 conversion " ) ) ;
2020-08-29 13:27:11 +00:00
break ;
case UTF8ConversionError : : SourceExhausted :
2022-10-23 02:55:20 +00:00
scope . throwException ( globalObject , createError ( globalObject , " Source exhausted during UTF8 conversion " ) ) ;
2020-08-29 13:27:11 +00:00
break ;
default :
RELEASE_ASSERT_NOT_REACHED ( ) ;
}
return { } ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
static EncodedJSValue printInternal ( JSGlobalObject * globalObject , CallFrame * callFrame , FILE * out )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2018-01-03 05:16:05 +00:00
if ( asyncTestExpectedPasses ) {
2022-10-23 02:55:20 +00:00
JSValue value = callFrame - > argument ( 0 ) ;
if ( value . isString ( ) & & WTF : : equal ( asString ( value ) - > value ( globalObject ) . impl ( ) , " Test262:AsyncTestComplete " ) ) {
2018-01-03 05:16:05 +00:00
asyncTestPasses + + ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
for ( unsigned i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
2017-08-12 16:48:01 +00:00
if ( i )
if ( EOF = = fputc ( ' ' , out ) )
goto fail ;
2022-10-23 02:55:20 +00:00
auto * jsString = callFrame - > uncheckedArgument ( i ) . toString ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
auto viewWithString = jsString - > viewWithUnderlyingString ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
auto string = cStringFromViewWithString ( globalObject , scope , viewWithString ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
fwrite ( string . data ( ) , sizeof ( char ) , string . length ( ) , out ) ;
if ( ferror ( out ) )
2017-08-12 16:48:01 +00:00
goto fail ;
}
fputc ( ' \n ' , out ) ;
fail :
fflush ( out ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionPrintStdOut , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
return printInternal ( globalObject , callFrame , stdout ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionPrintStdErr , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
return printInternal ( globalObject , callFrame , stderr ) ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDebug , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
auto * jsString = callFrame - > argument ( 0 ) . toString ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
auto viewWithString = jsString - > viewWithUnderlyingString ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
auto string = cStringFromViewWithString ( globalObject , scope , viewWithString ) ;
RETURN_IF_EXCEPTION ( scope , { } ) ;
fputs ( " --> " , stderr ) ;
fwrite ( string . data ( ) , sizeof ( char ) , string . length ( ) , stderr ) ;
fputc ( ' \n ' , stderr ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDescribe , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
if ( callFrame - > argumentCount ( ) < 1 )
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , toString ( callFrame - > argument ( 0 ) ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDescribeArray , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) < 1 )
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
JSObject * object = jsDynamicCast < JSObject * > ( vm , callFrame - > argument ( 0 ) ) ;
2017-08-12 16:48:01 +00:00
if ( ! object )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsNontrivialString ( vm , " <not object> " _s ) ) ;
return JSValue : : encode ( jsNontrivialString ( vm , toString ( " <Butterfly: " , RawPointer ( object - > butterfly ( ) ) , " ; public length: " , object - > getArrayLength ( ) , " ; vector length: " , object - > getVectorLength ( ) , " > " ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSleepSeconds , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) > = 1 ) {
Seconds seconds = Seconds ( callFrame - > argument ( 0 ) . toNumber ( globalObject ) ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
sleep ( seconds ) ;
}
return JSValue : : encode ( jsUndefined ( ) ) ;
}
class FunctionJSCStackFunctor {
public :
FunctionJSCStackFunctor ( StringBuilder & trace )
: m_trace ( trace )
{
2020-08-29 13:27:11 +00:00
}
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
StackVisitor : : Status operator ( ) ( StackVisitor & visitor ) const
{
m_trace . append ( makeString ( " " , visitor - > index ( ) , " " , visitor - > toString ( ) , ' \n ' ) ) ;
return StackVisitor : : Continue ;
}
2018-01-03 05:16:05 +00:00
2020-08-29 13:27:11 +00:00
private :
StringBuilder & m_trace ;
} ;
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionJSCStack , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
StringBuilder trace ;
trace . appendLiteral ( " --> Stack trace: \n " ) ;
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
FunctionJSCStackFunctor functor ( trace ) ;
2022-10-23 02:55:20 +00:00
callFrame - > iterate ( vm , functor ) ;
2020-08-29 13:27:11 +00:00
fprintf ( stderr , " %s " , trace . toString ( ) . utf8 ( ) . data ( ) ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionGCAndSweep , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
vm . heap . collectNow ( Sync , CollectionScope : : Full ) ;
return JSValue : : encode ( jsNumber ( vm . heap . sizeAfterLastFullCollection ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionFullGC , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
vm . heap . collectSync ( CollectionScope : : Full ) ;
return JSValue : : encode ( jsNumber ( vm . heap . sizeAfterLastFullCollection ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionEdenGC , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
vm . heap . collectSync ( CollectionScope : : Eden ) ;
return JSValue : : encode ( jsNumber ( vm . heap . sizeAfterLastEdenCollection ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionHeapSize , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
return JSValue : : encode ( jsNumber ( vm . heap . size ( ) ) ) ;
}
class JSCMemoryFootprint : public JSDestructibleObject {
using Base = JSDestructibleObject ;
public :
2022-10-23 02:55:20 +00:00
template < typename CellType , SubspaceAccess >
static CompleteSubspace * subspaceFor ( VM & vm )
{
return & vm . destructibleObjectSpace ;
}
2020-08-29 13:27:11 +00:00
JSCMemoryFootprint ( VM & vm , Structure * structure )
: Base ( vm , structure )
{ }
static Structure * createStructure ( VM & vm , JSGlobalObject * globalObject , JSValue prototype )
{
return Structure : : create ( vm , globalObject , prototype , TypeInfo ( ObjectType , StructureFlags ) , info ( ) ) ;
}
static JSCMemoryFootprint * create ( VM & vm , JSGlobalObject * globalObject )
{
Structure * structure = createStructure ( vm , globalObject , jsNull ( ) ) ;
2022-10-23 02:55:20 +00:00
JSCMemoryFootprint * footprint = new ( NotNull , allocateCell < JSCMemoryFootprint > ( vm . heap ) ) JSCMemoryFootprint ( vm , structure ) ;
2020-08-29 13:27:11 +00:00
footprint - > finishCreation ( vm ) ;
return footprint ;
}
void finishCreation ( VM & vm )
{
Base : : finishCreation ( vm ) ;
auto addProperty = [ & ] ( VM & vm , const char * name , JSValue value ) {
JSCMemoryFootprint : : addProperty ( vm , name , value ) ;
} ;
MemoryFootprint footprint = MemoryFootprint : : now ( ) ;
addProperty ( vm , " current " , jsNumber ( footprint . current ) ) ;
addProperty ( vm , " peak " , jsNumber ( footprint . peak ) ) ;
}
DECLARE_INFO ;
private :
void addProperty ( VM & vm , const char * name , JSValue value )
{
2022-10-23 02:55:20 +00:00
Identifier identifier = Identifier : : fromString ( vm , name ) ;
2020-08-29 13:27:11 +00:00
putDirect ( vm , identifier , value ) ;
}
} ;
const ClassInfo JSCMemoryFootprint : : s_info = { " MemoryFootprint " , & Base : : s_info , nullptr , nullptr , CREATE_METHOD_TABLE ( JSCMemoryFootprint ) } ;
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCreateMemoryFootprint , ( JSGlobalObject * globalObject , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( JSCMemoryFootprint : : create ( vm , globalObject ) ) ;
2020-08-29 13:27:11 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionResetMemoryPeak , ( JSGlobalObject * , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
MemoryFootprint : : resetPeak ( ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
2017-08-12 16:48:01 +00:00
}
// This function is not generally very helpful in 64-bit code as the tag and payload
// share a register. But in 32-bit JITed code the tag may not be checked if an
// optimization removes type checking requirements, such as in ===.
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionAddressOf , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
JSValue value = callFrame - > argument ( 0 ) ;
2017-08-12 16:48:01 +00:00
if ( ! value . isCell ( ) )
return JSValue : : encode ( jsUndefined ( ) ) ;
// Need to cast to uint64_t so bitwise_cast will play along.
uint64_t asNumber = reinterpret_cast < uint64_t > ( value . asCell ( ) ) ;
EncodedJSValue returnValue = JSValue : : encode ( jsNumber ( bitwise_cast < double > ( asNumber ) ) ) ;
return returnValue ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionVersion , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
// We need this function for compatibility with the Mozilla JS tests but for now
// we don't actually do any version-specific handling
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionRun , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String fileName = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
Vector < char > script ;
if ( ! fetchScriptFromLocalFileSystem ( fileName , script ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Could not open file. " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
GlobalObject * realm = GlobalObject : : create ( vm , GlobalObject : : createStructure ( vm , jsNull ( ) ) , Vector < String > ( ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSArray * array = constructEmptyArray ( realm , nullptr ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
for ( unsigned i = 1 ; i < callFrame - > argumentCount ( ) ; + + i ) {
array - > putDirectIndex ( realm , i - 1 , callFrame - > uncheckedArgument ( i ) ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
}
2022-10-23 02:55:20 +00:00
realm - > putDirect ( vm , Identifier : : fromString ( vm , " arguments " ) , array ) ;
2017-08-12 16:48:01 +00:00
NakedPtr < Exception > exception ;
StopWatch stopWatch ;
stopWatch . start ( ) ;
2022-10-23 02:55:20 +00:00
evaluate ( realm , jscSource ( script , SourceOrigin { absolutePath ( fileName ) } , fileName ) , JSValue ( ) , exception ) ;
2017-08-12 16:48:01 +00:00
stopWatch . stop ( ) ;
if ( exception ) {
2022-10-23 02:55:20 +00:00
throwException ( realm , scope , exception ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
return JSValue : : encode ( jsNumber ( stopWatch . getElapsedMS ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionRunString , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String source = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
GlobalObject * realm = GlobalObject : : create ( vm , GlobalObject : : createStructure ( vm , jsNull ( ) ) , Vector < String > ( ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSArray * array = constructEmptyArray ( realm , nullptr ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
for ( unsigned i = 1 ; i < callFrame - > argumentCount ( ) ; + + i ) {
array - > putDirectIndex ( realm , i - 1 , callFrame - > uncheckedArgument ( i ) ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
}
2022-10-23 02:55:20 +00:00
realm - > putDirect ( vm , Identifier : : fromString ( vm , " arguments " ) , array ) ;
2017-08-12 16:48:01 +00:00
NakedPtr < Exception > exception ;
2022-10-23 02:55:20 +00:00
evaluate ( realm , jscSource ( source , callFrame - > callerSourceOrigin ( vm ) ) , JSValue ( ) , exception ) ;
2017-08-12 16:48:01 +00:00
if ( exception ) {
2022-10-23 02:55:20 +00:00
scope . throwException ( realm , exception ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( realm ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionLoad , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
bool callerRelative = callFrame - > argument ( 1 ) . getString ( globalObject ) = = " caller relative " _s ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
String fileName = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
URL path ;
if ( callerRelative ) {
path = URL ( callFrame - > callerSourceOrigin ( vm ) . url ( ) , fileName ) ;
if ( ! path . isLocalFile ( ) )
return throwVMException ( globalObject , scope , createURIError ( globalObject , makeString ( " caller relative URL path is not a local file: " , path . string ( ) ) ) ) ;
} else
path = absolutePath ( fileName ) ;
2017-08-12 16:48:01 +00:00
Vector < char > script ;
2022-10-23 02:55:20 +00:00
if ( ! fetchScriptFromLocalFileSystem ( path . fileSystemPath ( ) , script ) )
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Could not open file. " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue result = evaluate ( globalObject , jscSource ( script , SourceOrigin { path } , fileName ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
if ( evaluationException )
2022-10-23 02:55:20 +00:00
throwException ( globalObject , scope , evaluationException ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( result ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionLoadString , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String sourceCode = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue result = evaluate ( globalObject , jscSource ( sourceCode , callFrame - > callerSourceOrigin ( vm ) ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
if ( evaluationException )
2022-10-23 02:55:20 +00:00
throwException ( globalObject , scope , evaluationException ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( result ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionReadFile , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String fileName = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
bool isBinary = false ;
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) > 1 ) {
String type = callFrame - > argument ( 1 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
if ( type ! = " binary " )
2022-10-23 02:55:20 +00:00
return throwVMError ( globalObject , scope , " Expected 'binary' as second argument. " ) ;
2017-08-12 16:48:01 +00:00
isBinary = true ;
}
2020-08-29 13:27:11 +00:00
RefPtr < Uint8Array > content = fillBufferWithContentsOfFile ( fileName ) ;
if ( ! content )
2022-10-23 02:55:20 +00:00
return throwVMError ( globalObject , scope , " Could not open file. " ) ;
2017-08-12 16:48:01 +00:00
if ( ! isBinary )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , String : : fromUTF8WithLatin1Fallback ( content - > data ( ) , content - > length ( ) ) ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
Structure * structure = globalObject - > typedArrayStructure ( TypeUint8 ) ;
2020-08-29 13:27:11 +00:00
JSObject * result = JSUint8Array : : create ( vm , structure , WTFMove ( content ) ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
return JSValue : : encode ( result ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCheckSyntax , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String fileName = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
Vector < char > script ;
if ( ! fetchScriptFromLocalFileSystem ( fileName , script ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Could not open file. " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
StopWatch stopWatch ;
stopWatch . start ( ) ;
JSValue syntaxException ;
2022-10-23 02:55:20 +00:00
bool validSyntax = checkSyntax ( globalObject , jscSource ( script , SourceOrigin { absolutePath ( fileName ) } , fileName ) , & syntaxException ) ;
2017-08-12 16:48:01 +00:00
stopWatch . stop ( ) ;
if ( ! validSyntax )
2022-10-23 02:55:20 +00:00
throwException ( globalObject , scope , syntaxException ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsNumber ( stopWatch . getElapsedMS ( ) ) ) ;
}
# if ENABLE(SAMPLING_FLAGS)
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSetSamplingFlags , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
for ( unsigned i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
unsigned flag = static_cast < unsigned > ( callFrame - > uncheckedArgument ( i ) . toNumber ( globalObject ) ) ;
2017-08-12 16:48:01 +00:00
if ( ( flag > = 1 ) & & ( flag < = 32 ) )
SamplingFlags : : setFlag ( flag ) ;
}
return JSValue : : encode ( jsNull ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionClearSamplingFlags , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
for ( unsigned i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
unsigned flag = static_cast < unsigned > ( callFrame - > uncheckedArgument ( i ) . toNumber ( globalObject ) ) ;
2017-08-12 16:48:01 +00:00
if ( ( flag > = 1 ) & & ( flag < = 32 ) )
SamplingFlags : : clearFlag ( flag ) ;
}
return JSValue : : encode ( jsNull ( ) ) ;
}
# endif
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionGetRandomSeed , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsNumber ( globalObject - > weakRandom ( ) . seed ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSetRandomSeed , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
unsigned seed = callFrame - > argument ( 0 ) . toUInt32 ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
globalObject - > weakRandom ( ) . setSeed ( seed ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionIsRope , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
JSValue argument = callFrame - > argument ( 0 ) ;
2017-08-12 16:48:01 +00:00
if ( ! argument . isString ( ) )
return JSValue : : encode ( jsBoolean ( false ) ) ;
const StringImpl * impl = asString ( argument ) - > tryGetValueImpl ( ) ;
return JSValue : : encode ( jsBoolean ( ! impl ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCallerSourceOrigin , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2018-01-03 05:16:05 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
SourceOrigin sourceOrigin = callFrame - > callerSourceOrigin ( vm ) ;
if ( sourceOrigin . url ( ) . isNull ( ) )
2018-01-03 05:16:05 +00:00
return JSValue : : encode ( jsNull ( ) ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , sourceOrigin . string ( ) ) ) ;
2018-01-03 05:16:05 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionReadline , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
Vector < char , 256 > line ;
int c ;
while ( ( c = getchar ( ) ) ! = EOF ) {
// FIXME: Should we also break on \r?
if ( c = = ' \n ' )
break ;
line . append ( c ) ;
}
line . append ( ' \0 ' ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( globalObject - > vm ( ) , line . data ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionPreciseTime , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2020-08-29 13:27:11 +00:00
return JSValue : : encode ( jsNumber ( WallTime : : now ( ) . secondsSinceEpoch ( ) . value ( ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionNeverInlineFunction , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( setNeverInline ( globalObject , callFrame ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionNoDFG , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( setNeverOptimize ( globalObject , callFrame ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionNoFTL , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) ) {
FunctionExecutable * executable = getExecutableForFunction ( callFrame - > argument ( 0 ) ) ;
2020-08-29 13:27:11 +00:00
if ( executable )
executable - > setNeverFTLOptimize ( true ) ;
2017-08-12 16:48:01 +00:00
}
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionNoOSRExitFuzzing , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
return JSValue : : encode ( setCannotUseOSRExitFuzzing ( globalObject , callFrame ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionOptimizeNextInvocation , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( optimizeNextInvocation ( globalObject , callFrame ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionNumberOfDFGCompiles , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( numberOfDFGCompiles ( globalObject , callFrame ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCallerIsOMGCompiled , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
if ( ! Options : : useBBQTierUpChecks ( ) )
return JSValue : : encode ( jsBoolean ( true ) ) ;
CallerFunctor wasmToJSFrame ;
StackVisitor : : visit ( callFrame , vm , wasmToJSFrame ) ;
if ( ! wasmToJSFrame . callerFrame ( ) - > isAnyWasmCallee ( ) )
return throwVMError ( globalObject , scope , " caller is not a wasm->js import function " ) ;
// We have a wrapper frame that we generate for imports. If we ever can direct call from wasm we would need to change this.
ASSERT ( ! wasmToJSFrame . callerFrame ( ) - > callee ( ) . isWasm ( ) ) ;
CallerFunctor wasmFrame ;
StackVisitor : : visit ( wasmToJSFrame . callerFrame ( ) , vm , wasmFrame ) ;
ASSERT ( wasmFrame . callerFrame ( ) - > callee ( ) . isWasm ( ) ) ;
# if ENABLE(WEBASSEMBLY)
auto mode = wasmFrame . callerFrame ( ) - > callee ( ) . asWasmCallee ( ) - > compilationMode ( ) ;
return JSValue : : encode ( jsBoolean ( mode = = Wasm : : CompilationMode : : OMGMode | | mode = = Wasm : : CompilationMode : : OMGForOSREntryMode ) ) ;
# endif
RELEASE_ASSERT_NOT_REACHED ( ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
Message : : Message ( Content & & contents , int32_t index )
2017-08-12 16:48:01 +00:00
: m_contents ( WTFMove ( contents ) )
, m_index ( index )
{
}
Message : : ~ Message ( )
{
}
Worker : : Worker ( Workers & workers )
: m_workers ( workers )
{
auto locker = holdLock ( m_workers . m_lock ) ;
m_workers . m_workers . append ( this ) ;
* currentWorker ( ) = this ;
}
Worker : : ~ Worker ( )
{
auto locker = holdLock ( m_workers . m_lock ) ;
RELEASE_ASSERT ( isOnList ( ) ) ;
remove ( ) ;
}
void Worker : : enqueue ( const AbstractLocker & , RefPtr < Message > message )
{
m_messages . append ( message ) ;
}
RefPtr < Message > Worker : : dequeue ( )
{
auto locker = holdLock ( m_workers . m_lock ) ;
while ( m_messages . isEmpty ( ) )
m_workers . m_condition . wait ( m_workers . m_lock ) ;
return m_messages . takeFirst ( ) ;
}
Worker & Worker : : current ( )
{
return * * currentWorker ( ) ;
}
ThreadSpecific < Worker * > & Worker : : currentWorker ( )
{
static ThreadSpecific < Worker * > * result ;
static std : : once_flag flag ;
std : : call_once (
flag ,
[ ] ( ) {
result = new ThreadSpecific < Worker * > ( ) ;
} ) ;
return * result ;
}
Workers : : Workers ( )
{
}
Workers : : ~ Workers ( )
{
UNREACHABLE_FOR_PLATFORM ( ) ;
}
template < typename Func >
void Workers : : broadcast ( const Func & func )
{
auto locker = holdLock ( m_lock ) ;
for ( Worker * worker = m_workers . begin ( ) ; worker ! = m_workers . end ( ) ; worker = worker - > next ( ) ) {
if ( worker ! = & Worker : : current ( ) )
func ( locker , * worker ) ;
}
m_condition . notifyAll ( ) ;
}
2020-08-29 13:27:11 +00:00
void Workers : : report ( const String & string )
2017-08-12 16:48:01 +00:00
{
auto locker = holdLock ( m_lock ) ;
m_reports . append ( string . isolatedCopy ( ) ) ;
m_condition . notifyAll ( ) ;
}
String Workers : : tryGetReport ( )
{
auto locker = holdLock ( m_lock ) ;
if ( m_reports . isEmpty ( ) )
return String ( ) ;
return m_reports . takeFirst ( ) ;
}
String Workers : : getReport ( )
{
auto locker = holdLock ( m_lock ) ;
while ( m_reports . isEmpty ( ) )
m_condition . wait ( m_lock ) ;
return m_reports . takeFirst ( ) ;
}
Workers & Workers : : singleton ( )
{
static Workers * result ;
static std : : once_flag flag ;
std : : call_once (
flag ,
[ ] {
result = new Workers ( ) ;
} ) ;
return * result ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarCreateRealm , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
GlobalObject * result = GlobalObject : : create ( vm , GlobalObject : : createStructure ( vm , jsNull ( ) ) , Vector < String > ( ) ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( result - > getDirect ( vm , Identifier : : fromString ( vm , " $ " ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarEvalScript , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String sourceCode = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
JSValue global = callFrame - > thisValue ( ) . get ( globalObject , Identifier : : fromString ( vm , " global " ) ) ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
GlobalObject * realm = jsDynamicCast < GlobalObject * > ( vm , global ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
if ( ! realm )
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Expected global to point to a global object " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue result = evaluate ( realm , jscSource ( sourceCode , callFrame - > callerSourceOrigin ( vm ) ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
if ( evaluationException )
2022-10-23 02:55:20 +00:00
throwException ( globalObject , scope , evaluationException ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( result ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentStart , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String sourceCode = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
Lock didStartLock ;
Condition didStartCondition ;
bool didStart = false ;
2022-10-23 02:55:20 +00:00
auto isGigacageMemoryExhausted = [ & ] ( Gigacage : : Kind kind ) {
if ( ! Gigacage : : isEnabled ( kind ) )
return false ;
if ( Gigacage : : footprint ( kind ) < Gigacage : : size ( kind ) * 0.8 )
return false ;
return true ;
} ;
if ( isGigacageMemoryExhausted ( Gigacage : : JSValue ) | | isGigacageMemoryExhausted ( Gigacage : : Primitive ) )
return JSValue : : encode ( throwOutOfMemoryError ( globalObject , scope , " Gigacage is exhausted " _s ) ) ;
String workerPath = " worker " _s ;
if ( ! callFrame - > argument ( 1 ) . isUndefined ( ) ) {
workerPath = callFrame - > argument ( 1 ) . toWTFString ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
}
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
Thread : : create (
2017-08-12 16:48:01 +00:00
" JSC Agent " ,
2022-10-23 02:55:20 +00:00
[ sourceCode = sourceCode . isolatedCopy ( ) , workerPath = workerPath . isolatedCopy ( ) , & didStartLock , & didStartCondition , & didStart ] ( ) {
CommandLine commandLine ( CommandLine : : CommandLineForWorkers ) ;
2017-08-12 16:48:01 +00:00
commandLine . m_interactive = false ;
runJSC (
2018-01-03 05:16:05 +00:00
commandLine , true ,
2020-08-29 13:27:11 +00:00
[ & ] ( VM & , GlobalObject * globalObject , bool & success ) {
2017-08-12 16:48:01 +00:00
// Notify the thread that started us that we have registered a worker.
{
auto locker = holdLock ( didStartLock ) ;
didStart = true ;
didStartCondition . notifyOne ( ) ;
}
NakedPtr < Exception > evaluationException ;
JSValue result ;
2022-10-23 02:55:20 +00:00
result = evaluate ( globalObject , jscSource ( sourceCode , SourceOrigin ( URL ( { } , workerPath ) ) ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
if ( evaluationException )
result = evaluationException - > value ( ) ;
2022-10-23 02:55:20 +00:00
checkException ( globalObject , true , evaluationException , result , commandLine , success ) ;
2017-08-12 16:48:01 +00:00
if ( ! success )
exit ( 1 ) ;
} ) ;
2020-08-29 13:27:11 +00:00
} ) - > detach ( ) ;
2017-08-12 16:48:01 +00:00
{
auto locker = holdLock ( didStartLock ) ;
while ( ! didStart )
didStartCondition . wait ( didStartLock ) ;
}
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentReceiveBroadcast , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
JSValue callback = callFrame - > argument ( 0 ) ;
auto callData = getCallData ( vm , callback ) ;
if ( callData . type = = CallData : : Type : : None )
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Expected callback " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
RefPtr < Message > message ;
{
ReleaseHeapAccessScope releaseAccess ( vm . heap ) ;
message = Worker : : current ( ) . dequeue ( ) ;
}
2022-10-23 02:55:20 +00:00
auto content = message - > releaseContents ( ) ;
JSValue result = ( [ & ] ( ) - > JSValue {
if ( WTF : : holds_alternative < ArrayBufferContents > ( content ) ) {
auto nativeBuffer = ArrayBuffer : : create ( WTF : : get < ArrayBufferContents > ( WTFMove ( content ) ) ) ;
ArrayBufferSharingMode sharingMode = nativeBuffer - > sharingMode ( ) ;
return JSArrayBuffer : : create ( vm , globalObject - > arrayBufferStructure ( sharingMode ) , WTFMove ( nativeBuffer ) ) ;
}
# if ENABLE(WEBASSEMBLY)
if ( WTF : : holds_alternative < Ref < Wasm : : MemoryHandle > > ( content ) ) {
JSWebAssemblyMemory * jsMemory = JSC : : JSWebAssemblyMemory : : tryCreate ( globalObject , vm , globalObject - > webAssemblyMemoryStructure ( ) ) ;
scope . releaseAssertNoException ( ) ;
Ref < Wasm : : Memory > memory = Wasm : : Memory : : create ( WTF : : get < Ref < Wasm : : MemoryHandle > > ( WTFMove ( content ) ) ,
[ & vm ] ( Wasm : : Memory : : NotifyPressure ) { vm . heap . collectAsync ( CollectionScope : : Full ) ; } ,
[ & vm ] ( Wasm : : Memory : : SyncTryToReclaim ) { vm . heap . collectSync ( CollectionScope : : Full ) ; } ,
[ & vm , jsMemory ] ( Wasm : : Memory : : GrowSuccess , Wasm : : PageCount oldPageCount , Wasm : : PageCount newPageCount ) { jsMemory - > growSuccessCallback ( vm , oldPageCount , newPageCount ) ; } ) ;
jsMemory - > adopt ( WTFMove ( memory ) ) ;
return jsMemory ;
}
# endif
return jsUndefined ( ) ;
} ) ( ) ;
2017-08-12 16:48:01 +00:00
MarkedArgumentBuffer args ;
2022-10-23 02:55:20 +00:00
args . append ( result ) ;
2017-08-12 16:48:01 +00:00
args . append ( jsNumber ( message - > index ( ) ) ) ;
2020-08-29 13:27:11 +00:00
if ( UNLIKELY ( args . hasOverflowed ( ) ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( throwOutOfMemoryError ( globalObject , scope ) ) ;
RELEASE_AND_RETURN ( scope , JSValue : : encode ( call ( globalObject , callback , callData , jsNull ( ) , args ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentReport , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
String report = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
Workers : : singleton ( ) . report ( report ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentSleep , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) > = 1 ) {
Seconds seconds = Seconds : : fromMilliseconds ( callFrame - > argument ( 0 ) . toNumber ( globalObject ) ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
sleep ( seconds ) ;
}
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentBroadcast , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
int32_t index = callFrame - > argument ( 1 ) . toInt32 ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2022-10-23 02:55:20 +00:00
JSArrayBuffer * jsBuffer = jsDynamicCast < JSArrayBuffer * > ( vm , callFrame - > argument ( 0 ) ) ;
if ( jsBuffer & & jsBuffer - > isShared ( ) ) {
Workers : : singleton ( ) . broadcast (
[ & ] ( const AbstractLocker & locker , Worker & worker ) {
ArrayBuffer * nativeBuffer = jsBuffer - > impl ( ) ;
ArrayBufferContents contents ;
nativeBuffer - > transferTo ( vm , contents ) ; // "transferTo" means "share" if the buffer is shared.
RefPtr < Message > message = adoptRef ( new Message ( WTFMove ( contents ) , index ) ) ;
worker . enqueue ( locker , message ) ;
} ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
# if ENABLE(WEBASSEMBLY)
JSWebAssemblyMemory * memory = jsDynamicCast < JSWebAssemblyMemory * > ( vm , callFrame - > argument ( 0 ) ) ;
if ( memory & & memory - > memory ( ) . sharingMode ( ) = = Wasm : : MemorySharingMode : : Shared ) {
Workers : : singleton ( ) . broadcast (
[ & ] ( const AbstractLocker & locker , Worker & worker ) {
Ref < Wasm : : MemoryHandle > handle { memory - > memory ( ) . handle ( ) } ;
RefPtr < Message > message = adoptRef ( new Message ( WTFMove ( handle ) , index ) ) ;
worker . enqueue ( locker , message ) ;
} ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
# endif
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Not supported object " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentGetReport , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
String string = Workers : : singleton ( ) . tryGetReport ( ) ;
if ( ! string )
return JSValue : : encode ( jsNull ( ) ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , string ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentLeaving , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDollarAgentMonotonicNow , ( JSGlobalObject * , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
return JSValue : : encode ( jsNumber ( MonotonicTime : : now ( ) . secondsSinceEpoch ( ) . milliseconds ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionWaitForReport , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
String string ;
{
ReleaseHeapAccessScope releaseAccess ( vm . heap ) ;
string = Workers : : singleton ( ) . getReport ( ) ;
}
if ( ! string )
return JSValue : : encode ( jsNull ( ) ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , string ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionHeapCapacity , ( JSGlobalObject * globalObject , CallFrame * ) )
2018-01-03 05:16:05 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2018-01-03 05:16:05 +00:00
return JSValue : : encode ( jsNumber ( vm . heap . capacity ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionFlashHeapAccess , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2018-01-03 05:16:05 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2018-01-03 05:16:05 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2020-08-29 13:27:11 +00:00
double sleepTimeMs = 0 ;
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) > = 1 ) {
sleepTimeMs = callFrame - > argument ( 0 ) . toNumber ( globalObject ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
}
2020-08-29 13:27:11 +00:00
vm . heap . releaseAccess ( ) ;
if ( sleepTimeMs )
sleep ( Seconds : : fromMilliseconds ( sleepTimeMs ) ) ;
2018-01-03 05:16:05 +00:00
vm . heap . acquireAccess ( ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDisableRichSourceInfo , ( JSGlobalObject * , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
supportsRichSourceInfo = false ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionMallocInALoop , ( JSGlobalObject * , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
Vector < void * > ptrs ;
for ( unsigned i = 0 ; i < 5000 ; + + i )
ptrs . append ( fastMalloc ( 1024 * 2 ) ) ;
for ( void * ptr : ptrs )
fastFree ( ptr ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionTotalCompileTime , ( JSGlobalObject * , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
# if ENABLE(JIT)
return JSValue : : encode ( jsNumber ( JIT : : totalCompileTime ( ) . milliseconds ( ) ) ) ;
# else
return JSValue : : encode ( jsNumber ( 0 ) ) ;
# endif
}
2017-08-12 16:48:01 +00:00
template < typename ValueType >
2020-08-29 13:27:11 +00:00
typename std : : enable_if < ! std : : is_fundamental < ValueType > : : value > : : type addOption ( VM & , JSObject * , const Identifier & , ValueType ) { }
2017-08-12 16:48:01 +00:00
template < typename ValueType >
2020-08-29 13:27:11 +00:00
typename std : : enable_if < std : : is_fundamental < ValueType > : : value > : : type addOption ( VM & vm , JSObject * optionsObject , const Identifier & identifier , ValueType value )
2017-08-12 16:48:01 +00:00
{
optionsObject - > putDirect ( vm , identifier , JSValue ( value ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionJSCOptions , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
JSObject * optionsObject = constructEmptyObject ( globalObject ) ;
# define READ_OPTION(type_, name_, defaultValue_, availability_, description_) \
addOption ( vm , optionsObject , Identifier : : fromString ( vm , # name_ ) , Options : : name_ ( ) ) ;
FOR_EACH_JSC_OPTION ( READ_OPTION )
# undef READ_OPTION
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( optionsObject ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionReoptimizationRetryCount , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) < 1 )
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
2022-10-23 02:55:20 +00:00
CodeBlock * block = getSomeBaselineCodeBlockForFunction ( callFrame - > argument ( 0 ) ) ;
2017-08-12 16:48:01 +00:00
if ( ! block )
return JSValue : : encode ( jsNumber ( 0 ) ) ;
return JSValue : : encode ( jsNumber ( block - > reoptimizationRetryCounter ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionTransferArrayBuffer , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
if ( callFrame - > argumentCount ( ) < 1 )
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Not enough arguments " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSArrayBuffer * buffer = jsDynamicCast < JSArrayBuffer * > ( vm , callFrame - > argument ( 0 ) ) ;
2017-08-12 16:48:01 +00:00
if ( ! buffer )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Expected an array buffer " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
ArrayBufferContents dummyContents ;
2018-01-03 05:16:05 +00:00
buffer - > impl ( ) - > transferTo ( vm , dummyContents ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionFailNextNewCodeBlock , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
vm . setFailNextNewCodeBlock ( ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionQuit , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
vm . codeCache ( ) - > write ( vm ) ;
2017-08-12 16:48:01 +00:00
jscExit ( EXIT_SUCCESS ) ;
# if COMPILER(MSVC)
// Without this, Visual Studio will complain that this method does not return a value.
return JSValue : : encode ( jsUndefined ( ) ) ;
# endif
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionFalse , ( JSGlobalObject * , CallFrame * ) )
{
return JSValue : : encode ( jsBoolean ( false ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionUndefined1 , ( JSGlobalObject * , CallFrame * ) )
{
return JSValue : : encode ( jsUndefined ( ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionUndefined2 , ( JSGlobalObject * , CallFrame * ) )
{
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionIsInt32 , ( JSGlobalObject * , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
for ( size_t i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
if ( ! callFrame - > argument ( i ) . isInt32 ( ) )
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsBoolean ( false ) ) ;
}
return JSValue : : encode ( jsBoolean ( true ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionIsPureNaN , ( JSGlobalObject * , CallFrame * callFrame ) )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
for ( size_t i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
JSValue value = callFrame - > argument ( i ) ;
2020-08-29 13:27:11 +00:00
if ( ! value . isNumber ( ) )
return JSValue : : encode ( jsBoolean ( false ) ) ;
double number = value . asNumber ( ) ;
if ( ! std : : isnan ( number ) )
return JSValue : : encode ( jsBoolean ( false ) ) ;
if ( isImpureNaN ( number ) )
return JSValue : : encode ( jsBoolean ( false ) ) ;
}
return JSValue : : encode ( jsBoolean ( true ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionIdentity , ( JSGlobalObject * , CallFrame * callFrame ) )
{
return JSValue : : encode ( callFrame - > argument ( 0 ) ) ;
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionEffectful42 , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
return JSValue : : encode ( jsNumber ( 42 ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionMakeMasquerader , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
return JSValue : : encode ( InternalFunction : : createFunctionThatMasqueradesAsUndefined ( vm , globalObject , 0 , " IsHTMLDDA " _s , functionCallMasquerader ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCallMasquerader , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsNull ( ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionHasCustomProperties , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
JSValue value = callFrame - > argument ( 0 ) ;
2017-08-12 16:48:01 +00:00
if ( value . isObject ( ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsBoolean ( asObject ( value ) - > hasCustomProperties ( globalObject - > vm ( ) ) ) ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsBoolean ( false ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDumpTypesForAllVariables , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
vm . dumpTypeProfilerData ( ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionDrainMicrotasks , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
vm . drainMicrotasks ( ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSetTimeout , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
// FIXME: This means we can't pass any internal function but I don't think that's common for testing.
auto callback = jsDynamicCast < JSFunction * > ( vm , callFrame - > argument ( 0 ) ) ;
if ( ! callback )
return throwVMTypeError ( globalObject , scope , " First argument is not a JS function " _s ) ;
// FIXME: We don't look at the timeout parameter because we don't have a schedule work later API.
vm . deferredWorkTimer - > addPendingWork ( vm , callback , { } ) ;
vm . deferredWorkTimer - > scheduleWorkSoon ( callback , [ callback ] {
JSGlobalObject * globalObject = callback - > globalObject ( ) ;
VM & vm = globalObject - > vm ( ) ;
MarkedArgumentBuffer args ;
call ( globalObject , callback , jsUndefined ( ) , args , " You shouldn't see this... " ) ;
vm . deferredWorkTimer - > cancelPendingWork ( callback ) ;
} ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionReleaseWeakRefs , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
vm . finalizeSynchronousJSExecution ( ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionFinalizationRegistryLiveCount , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
auto * finalizationRegistry = jsDynamicCast < JSFinalizationRegistry * > ( vm , callFrame - > argument ( 0 ) ) ;
if ( ! finalizationRegistry )
return throwVMTypeError ( globalObject , scope , " first argument is not a finalizationRegistry " _s ) ;
auto locker = holdLock ( finalizationRegistry - > cellLock ( ) ) ;
return JSValue : : encode ( jsNumber ( finalizationRegistry - > liveCount ( locker ) ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionFinalizationRegistryDeadCount , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
auto * finalizationRegistry = jsDynamicCast < JSFinalizationRegistry * > ( vm , callFrame - > argument ( 0 ) ) ;
if ( ! finalizationRegistry )
return throwVMTypeError ( globalObject , scope , " first argument is not a finalizationRegistry " _s ) ;
auto locker = holdLock ( finalizationRegistry - > cellLock ( ) ) ;
return JSValue : : encode ( jsNumber ( finalizationRegistry - > deadCount ( locker ) ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionIs32BitPlatform , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
# if USE(JSVALUE64)
return JSValue : : encode ( JSValue ( JSC : : JSValue : : JSFalse ) ) ;
# else
return JSValue : : encode ( JSValue ( JSC : : JSValue : : JSTrue ) ) ;
# endif
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCreateGlobalObject , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( GlobalObject : : create ( vm , GlobalObject : : createStructure ( vm , jsNull ( ) ) , Vector < String > ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionCreateHeapBigInt , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
JSValue argument = callFrame - > argument ( 0 ) ;
JSValue bigInt = argument . toBigInt ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
# if USE(BIGINT32)
if ( bigInt . isHeapBigInt ( ) )
return JSValue : : encode ( bigInt ) ;
ASSERT ( bigInt . isBigInt32 ( ) ) ;
int32_t value = bigInt . bigInt32AsInt32 ( ) ;
RELEASE_AND_RETURN ( scope , JSValue : : encode ( JSBigInt : : createFrom ( globalObject , value ) ) ) ;
# else
return JSValue : : encode ( bigInt ) ;
# endif
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
# if USE(BIGINT32)
JSC_DEFINE_HOST_FUNCTION ( functionCreateBigInt32 , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
JSValue argument = callFrame - > argument ( 0 ) ;
JSValue bigIntValue = argument . toBigInt ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
if ( bigIntValue . isBigInt32 ( ) )
return JSValue : : encode ( bigIntValue ) ;
ASSERT ( bigIntValue . isHeapBigInt ( ) ) ;
JSBigInt * bigInt = jsCast < JSBigInt * > ( bigIntValue ) ;
if ( ! bigInt - > length ( ) )
return JSValue : : encode ( jsBigInt32 ( 0 ) ) ;
if ( bigInt - > length ( ) = = 1 ) {
JSBigInt : : Digit digit = bigInt - > digit ( 0 ) ;
if ( bigInt - > sign ( ) ) {
if ( digit < = static_cast < uint64_t > ( - static_cast < int64_t > ( INT32_MIN ) ) )
return JSValue : : encode ( jsBigInt32 ( static_cast < int32_t > ( - static_cast < int64_t > ( digit ) ) ) ) ;
} else {
if ( digit < = INT32_MAX )
return JSValue : : encode ( jsBigInt32 ( static_cast < int32_t > ( digit ) ) ) ;
}
}
throwTypeError ( globalObject , scope , " Out of range of BigInt32 " _s ) ;
return { } ;
}
# endif
JSC_DEFINE_HOST_FUNCTION ( functionUseBigInt32 , ( JSGlobalObject * , CallFrame * ) )
{
# if USE(BIGINT32)
return JSValue : : encode ( jsBoolean ( true ) ) ;
# else
return JSValue : : encode ( jsBoolean ( false ) ) ;
# endif
}
JSC_DEFINE_HOST_FUNCTION ( functionIsBigInt32 , ( JSGlobalObject * , CallFrame * callFrame ) )
{
# if USE(BIGINT32)
return JSValue : : encode ( jsBoolean ( callFrame - > argument ( 0 ) . isBigInt32 ( ) ) ) ;
# else
UNUSED_PARAM ( callFrame ) ;
return JSValue : : encode ( jsBoolean ( false ) ) ;
# endif
}
JSC_DEFINE_HOST_FUNCTION ( functionIsHeapBigInt , ( JSGlobalObject * , CallFrame * callFrame ) )
{
return JSValue : : encode ( jsBoolean ( callFrame - > argument ( 0 ) . isHeapBigInt ( ) ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionCheckModuleSyntax , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
String source = callFrame - > argument ( 0 ) . toWTFString ( globalObject ) ;
2017-08-12 16:48:01 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
StopWatch stopWatch ;
stopWatch . start ( ) ;
ParserError error ;
2022-10-23 02:55:20 +00:00
bool validSyntax = checkModuleSyntax ( globalObject , jscSource ( source , { } , String ( ) , TextPosition ( ) , SourceProviderSourceType : : Module ) , error ) ;
2018-01-03 05:16:05 +00:00
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
2017-08-12 16:48:01 +00:00
stopWatch . stop ( ) ;
if ( ! validSyntax )
2022-10-23 02:55:20 +00:00
throwException ( globalObject , scope , jsNontrivialString ( vm , toString ( " SyntaxError: " , error . message ( ) , " : " , error . line ( ) ) ) ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsNumber ( stopWatch . getElapsedMS ( ) ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionPlatformSupportsSamplingProfiler , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
# if ENABLE(SAMPLING_PROFILER)
return JSValue : : encode ( JSValue ( JSC : : JSValue : : JSTrue ) ) ;
# else
return JSValue : : encode ( JSValue ( JSC : : JSValue : : JSFalse ) ) ;
# endif
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionGenerateHeapSnapshot , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
JSLockHolder lock ( vm ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2020-08-29 13:27:11 +00:00
HeapSnapshotBuilder snapshotBuilder ( vm . ensureHeapProfiler ( ) ) ;
2017-08-12 16:48:01 +00:00
snapshotBuilder . buildSnapshot ( ) ;
String jsonString = snapshotBuilder . json ( ) ;
2022-10-23 02:55:20 +00:00
EncodedJSValue result = JSValue : : encode ( JSONParse ( globalObject , jsonString ) ) ;
2018-01-03 05:16:05 +00:00
scope . releaseAssertNoException ( ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionGenerateHeapSnapshotForGCDebugging , ( JSGlobalObject * globalObject , CallFrame * ) )
2020-08-29 13:27:11 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
JSLockHolder lock ( vm ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
String jsonString ;
{
DeferGCForAWhile deferGC ( vm . heap ) ; // Prevent concurrent GC from interfering with the full GC that the snapshot does.
HeapSnapshotBuilder snapshotBuilder ( vm . ensureHeapProfiler ( ) , HeapSnapshotBuilder : : SnapshotType : : GCDebuggingSnapshot ) ;
snapshotBuilder . buildSnapshot ( ) ;
jsonString = snapshotBuilder . json ( ) ;
}
scope . releaseAssertNoException ( ) ;
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , jsonString ) ) ;
2020-08-29 13:27:11 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionResetSuperSamplerState , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
resetSuperSamplerState ( ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionEnsureArrayStorage , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
for ( unsigned i = 0 ; i < callFrame - > argumentCount ( ) ; + + i ) {
if ( JSObject * object = jsDynamicCast < JSObject * > ( vm , callFrame - > argument ( i ) ) )
2020-08-29 13:27:11 +00:00
object - > ensureArrayStorage ( vm ) ;
2017-08-12 16:48:01 +00:00
}
return JSValue : : encode ( jsUndefined ( ) ) ;
}
# if ENABLE(SAMPLING_PROFILER)
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionStartSamplingProfiler , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2020-08-29 13:27:11 +00:00
SamplingProfiler & samplingProfiler = vm . ensureSamplingProfiler ( WTF : : Stopwatch : : create ( ) ) ;
2017-08-12 16:48:01 +00:00
samplingProfiler . noticeCurrentThreadAsJSCExecutionThread ( ) ;
samplingProfiler . start ( ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSamplingProfilerStackTraces , ( JSGlobalObject * globalObject , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
if ( ! vm . samplingProfiler ( ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( throwException ( globalObject , scope , createError ( globalObject , " Sampling profiler was never started " _s ) ) ) ;
2017-08-12 16:48:01 +00:00
String jsonString = vm . samplingProfiler ( ) - > stackTracesAsJSON ( ) ;
2022-10-23 02:55:20 +00:00
EncodedJSValue result = JSValue : : encode ( JSONParse ( globalObject , jsonString ) ) ;
2018-01-03 05:16:05 +00:00
scope . releaseAssertNoException ( ) ;
2017-08-12 16:48:01 +00:00
return result ;
}
# endif // ENABLE(SAMPLING_PROFILER)
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionMaxArguments , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
return JSValue : : encode ( jsNumber ( JSC : : maxArguments ) ) ;
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionAsyncTestStart , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2018-01-03 05:16:05 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSValue numberOfAsyncPasses = callFrame - > argument ( 0 ) ;
2018-01-03 05:16:05 +00:00
if ( ! numberOfAsyncPasses . isUInt32 ( ) )
2022-10-23 02:55:20 +00:00
return throwVMError ( globalObject , scope , " Expected first argument to be a uint32 " _s ) ;
2017-08-12 16:48:01 +00:00
2018-01-03 05:16:05 +00:00
asyncTestExpectedPasses + = numberOfAsyncPasses . asUInt32 ( ) ;
return encodedJSUndefined ( ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionAsyncTestPassed , ( JSGlobalObject * , CallFrame * ) )
2017-08-12 16:48:01 +00:00
{
2018-01-03 05:16:05 +00:00
asyncTestPasses + + ;
return encodedJSUndefined ( ) ;
2017-08-12 16:48:01 +00:00
}
2018-01-03 05:16:05 +00:00
# if ENABLE(WEBASSEMBLY)
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionWebAssemblyMemoryMode , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
2017-08-12 16:48:01 +00:00
{
2022-10-23 02:55:20 +00:00
VM & vm = globalObject - > vm ( ) ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
2018-01-03 05:16:05 +00:00
2020-08-29 13:27:11 +00:00
if ( ! Wasm : : isSupported ( ) )
2022-10-23 02:55:20 +00:00
return throwVMTypeError ( globalObject , scope , " WebAssemblyMemoryMode should only be called if the useWebAssembly option is set " _s ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
if ( JSObject * object = callFrame - > argument ( 0 ) . getObject ( ) ) {
2018-01-03 05:16:05 +00:00
if ( auto * memory = jsDynamicCast < JSWebAssemblyMemory * > ( vm , object ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , makeString ( memory - > memory ( ) . mode ( ) ) ) ) ;
2018-01-03 05:16:05 +00:00
if ( auto * instance = jsDynamicCast < JSWebAssemblyInstance * > ( vm , object ) )
2022-10-23 02:55:20 +00:00
return JSValue : : encode ( jsString ( vm , makeString ( instance - > memoryMode ( ) ) ) ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
return throwVMTypeError ( globalObject , scope , " WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance " _s ) ;
2017-08-12 16:48:01 +00:00
}
2020-08-29 13:27:11 +00:00
# endif // ENABLE(WEBASSEMBLY)
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSC_DEFINE_HOST_FUNCTION ( functionSetUnhandledRejectionCallback , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
JSObject * object = callFrame - > argument ( 0 ) . getObject ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
if ( ! object | | ! object - > isCallable ( vm ) )
return throwVMTypeError ( globalObject , scope ) ;
globalObject - > setUnhandledRejectionCallback ( vm , object ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionAsDoubleNumber , ( JSGlobalObject * globalObject , CallFrame * callFrame ) )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_THROW_SCOPE ( vm ) ;
double num = callFrame - > argument ( 0 ) . toNumber ( globalObject ) ;
RETURN_IF_EXCEPTION ( scope , encodedJSValue ( ) ) ;
return JSValue : : encode ( jsDoubleNumber ( num ) ) ;
}
JSC_DEFINE_HOST_FUNCTION ( functionDropAllLocks , ( JSGlobalObject * globalObject , CallFrame * ) )
{
JSLock : : DropAllLocks dropAllLocks ( globalObject ) ;
return JSValue : : encode ( jsUndefined ( ) ) ;
}
2017-08-12 16:48:01 +00:00
// Use SEH for Release builds only to get rid of the crash report dialog
// (luckily the same tests fail in Release and Debug builds so far). Need to
// be in a separate main function because the jscmain function requires object
// unwinding.
# if COMPILER(MSVC) && !defined(_DEBUG)
# define TRY __try {
# define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
# else
# define TRY
# define EXCEPT(x)
# endif
int jscmain ( int argc , char * * argv ) ;
2022-10-23 02:55:20 +00:00
# if OS(DARWIN) || OS(LINUX)
static size_t memoryLimit ;
static void crashIfExceedingMemoryLimit ( )
{
if ( ! memoryLimit )
return ;
MemoryFootprint footprint = MemoryFootprint : : now ( ) ;
if ( footprint . current > memoryLimit ) {
dataLogLn ( " Crashing because current footprint: " , footprint . current , " exceeds limit: " , memoryLimit ) ;
CRASH ( ) ;
}
}
static void startMemoryMonitoringThreadIfNeeded ( )
{
char * memoryLimitString = getenv ( " JSCTEST_memoryLimit " ) ;
if ( ! memoryLimitString )
return ;
if ( sscanf ( memoryLimitString , " %zu " , & memoryLimit ) ! = 1 ) {
dataLogLn ( " WARNING: malformed JSCTEST_memoryLimit environment variable " ) ;
return ;
}
if ( ! memoryLimit )
return ;
Thread : : create ( " jsc Memory Monitor " , [ = ] {
while ( true ) {
sleep ( Seconds : : fromMilliseconds ( 5 ) ) ;
crashIfExceedingMemoryLimit ( ) ;
}
} ) ;
}
# endif // OS(DARWIN) || OS(LINUX)
2017-08-12 16:48:01 +00:00
static double s_desiredTimeout ;
static double s_timeoutMultiplier = 1.0 ;
2022-10-23 02:55:20 +00:00
static Seconds s_timeoutDuration ;
static Seconds s_maxAllowedCPUTime ;
static VM * s_vm ;
static void startTimeoutTimer ( Seconds duration )
{
Thread : : create ( " jsc Timeout Thread " , [ = ] ( ) {
sleep ( duration ) ;
VMInspector : : forEachVM ( [ & ] ( VM & vm ) - > VMInspector : : FunctorStatus {
if ( & vm ! = s_vm )
return VMInspector : : FunctorStatus : : Continue ;
vm . notifyNeedShellTimeoutCheck ( ) ;
return VMInspector : : FunctorStatus : : Done ;
} ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
if ( const char * timeoutString = getenv ( " JSCTEST_hardTimeout " ) ) {
double hardTimeoutInDouble = 0 ;
if ( sscanf ( timeoutString , " %lf " , & hardTimeoutInDouble ) ! = 1 )
dataLog ( " WARNING: hardTimeout string is malformed, got " , timeoutString , " but expected a number. Not using a timeout. \n " ) ;
else {
Seconds hardTimeout { hardTimeoutInDouble } ;
sleep ( hardTimeout ) ;
dataLogLn ( " HARD TIMEOUT after " , hardTimeout ) ;
exit ( EXIT_FAILURE ) ;
}
}
} ) ;
}
static void timeoutCheckCallback ( VM & vm )
{
RELEASE_ASSERT ( & vm = = s_vm ) ;
auto cpuTime = CPUTime : : forCurrentThread ( ) ;
if ( cpuTime > = s_maxAllowedCPUTime ) {
dataLog ( " Timed out after " , s_timeoutDuration , " seconds! \n " ) ;
CRASH ( ) ;
}
auto remainingTime = s_maxAllowedCPUTime - cpuTime ;
startTimeoutTimer ( remainingTime ) ;
}
static void initializeTimeoutIfNeeded ( )
2017-08-12 16:48:01 +00:00
{
if ( char * timeoutString = getenv ( " JSCTEST_timeout " ) ) {
if ( sscanf ( timeoutString , " %lf " , & s_desiredTimeout ) ! = 1 ) {
dataLog ( " WARNING: timeout string is malformed, got " , timeoutString ,
" but expected a number. Not using a timeout. \n " ) ;
2022-10-23 02:55:20 +00:00
} else
g_jscConfig . shellTimeoutCheckCallback = timeoutCheckCallback ;
2017-08-12 16:48:01 +00:00
}
}
2022-10-23 02:55:20 +00:00
static void startTimeoutThreadIfNeeded ( VM & vm )
{
if ( ! g_jscConfig . shellTimeoutCheckCallback )
return ;
s_vm = & vm ;
s_timeoutDuration = Seconds ( s_desiredTimeout * s_timeoutMultiplier ) ;
s_maxAllowedCPUTime = CPUTime : : forCurrentThread ( ) + s_timeoutDuration ;
Seconds timeoutDuration ( s_desiredTimeout * s_timeoutMultiplier ) ;
startTimeoutTimer ( timeoutDuration ) ;
}
2017-08-12 16:48:01 +00:00
int main ( int argc , char * * argv )
{
2022-10-23 02:55:20 +00:00
# if OS(DARWIN) && CPU(ARM_THUMB2)
2017-08-12 16:48:01 +00:00
// Enabled IEEE754 denormal support.
fenv_t env ;
fegetenv ( & env ) ;
env . __fpscr & = ~ 0x01000000u ;
fesetenv ( & env ) ;
# endif
# if OS(WINDOWS)
// Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
// testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
// error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
: : SetErrorMode ( 0 ) ;
2020-08-29 13:27:11 +00:00
_setmode ( _fileno ( stdout ) , _O_BINARY ) ;
_setmode ( _fileno ( stderr ) , _O_BINARY ) ;
2017-08-12 16:48:01 +00:00
# if defined(_DEBUG)
_CrtSetReportFile ( _CRT_WARN , _CRTDBG_FILE_STDERR ) ;
_CrtSetReportMode ( _CRT_WARN , _CRTDBG_MODE_FILE ) ;
_CrtSetReportFile ( _CRT_ERROR , _CRTDBG_FILE_STDERR ) ;
_CrtSetReportMode ( _CRT_ERROR , _CRTDBG_MODE_FILE ) ;
_CrtSetReportFile ( _CRT_ASSERT , _CRTDBG_FILE_STDERR ) ;
_CrtSetReportMode ( _CRT_ASSERT , _CRTDBG_MODE_FILE ) ;
# endif
timeBeginPeriod ( 1 ) ;
# endif
# if PLATFORM(GTK)
if ( ! setlocale ( LC_ALL , " " ) )
WTFLogAlways ( " Locale not supported by C library. \n \t Using the fallback 'C' locale. " ) ;
# endif
2022-10-23 02:55:20 +00:00
// Need to initialize WTF before we start any threads. Cannot initialize JSC
// yet, since that would do somethings that we'd like to defer until after we
2017-08-12 16:48:01 +00:00
// have a chance to parse options.
2022-10-23 02:55:20 +00:00
WTF : : initialize ( ) ;
2017-08-12 16:48:01 +00:00
// We can't use destructors in the following code because it uses Windows
// Structured Exception Handling
2022-10-23 02:55:20 +00:00
int res = EXIT_SUCCESS ;
2017-08-12 16:48:01 +00:00
TRY
res = jscmain ( argc , argv ) ;
2022-10-23 02:55:20 +00:00
EXCEPT ( res = EXIT_EXCEPTION )
2017-08-12 16:48:01 +00:00
finalizeStatsAtEndOfTesting ( ) ;
2022-10-23 02:55:20 +00:00
if ( getenv ( " JS_SHELL_WAIT_FOR_INPUT_TO_EXIT " ) ) {
WTF : : fastDisableScavenger ( ) ;
fprintf ( stdout , " \n js shell waiting for input to exit \n " ) ;
fflush ( stdout ) ;
getc ( stdin ) ;
}
2017-08-12 16:48:01 +00:00
jscExit ( res ) ;
}
static void dumpException ( GlobalObject * globalObject , JSValue exception )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_CATCH_SCOPE ( vm ) ;
# define CHECK_EXCEPTION() do { \
if ( scope . exception ( ) ) { \
scope . clearException ( ) ; \
return ; \
} \
} while ( false )
2022-10-23 02:55:20 +00:00
auto exceptionString = exception . toWTFString ( globalObject ) ;
CHECK_EXCEPTION ( ) ;
2020-08-29 13:27:11 +00:00
Expected < CString , UTF8ConversionError > expectedCString = exceptionString . tryGetUtf8 ( ) ;
if ( expectedCString )
printf ( " Exception: %s \n " , expectedCString . value ( ) . data ( ) ) ;
else
printf ( " Exception: <out of memory while extracting exception string> \n " ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
Identifier nameID = Identifier : : fromString ( vm , " name " ) ;
2018-01-03 05:16:05 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
Identifier fileNameID = Identifier : : fromString ( vm , " sourceURL " ) ;
2018-01-03 05:16:05 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
Identifier lineNumberID = Identifier : : fromString ( vm , " line " ) ;
2018-01-03 05:16:05 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
Identifier stackID = Identifier : : fromString ( vm , " stack " ) ;
2018-01-03 05:16:05 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
JSValue nameValue = exception . get ( globalObject , nameID ) ;
2017-08-12 16:48:01 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
JSValue fileNameValue = exception . get ( globalObject , fileNameID ) ;
2017-08-12 16:48:01 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
JSValue lineNumberValue = exception . get ( globalObject , lineNumberID ) ;
2017-08-12 16:48:01 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
JSValue stackValue = exception . get ( globalObject , stackID ) ;
2017-08-12 16:48:01 +00:00
CHECK_EXCEPTION ( ) ;
2022-10-23 02:55:20 +00:00
auto nameString = nameValue . toWTFString ( globalObject ) ;
CHECK_EXCEPTION ( ) ;
if ( nameString = = " SyntaxError " & & ( ! fileNameValue . isUndefinedOrNull ( ) | | ! lineNumberValue . isUndefinedOrNull ( ) ) ) {
auto fileNameString = fileNameValue . toWTFString ( globalObject ) ;
CHECK_EXCEPTION ( ) ;
auto lineNumberString = lineNumberValue . toWTFString ( globalObject ) ;
CHECK_EXCEPTION ( ) ;
printf ( " at %s:%s \n " , fileNameString . utf8 ( ) . data ( ) , lineNumberString . utf8 ( ) . data ( ) ) ;
2017-08-12 16:48:01 +00:00
}
2018-01-03 05:16:05 +00:00
if ( ! stackValue . isUndefinedOrNull ( ) ) {
2022-10-23 02:55:20 +00:00
auto stackString = stackValue . toWTFString ( globalObject ) ;
CHECK_EXCEPTION ( ) ;
2018-01-03 05:16:05 +00:00
if ( stackString . length ( ) )
printf ( " %s \n " , stackString . utf8 ( ) . data ( ) ) ;
}
2017-08-12 16:48:01 +00:00
# undef CHECK_EXCEPTION
}
2022-10-23 02:55:20 +00:00
static bool checkUncaughtException ( VM & vm , GlobalObject * globalObject , JSValue exception , const CommandLine & options )
2017-08-12 16:48:01 +00:00
{
2018-01-03 05:16:05 +00:00
const String & expectedExceptionName = options . m_uncaughtExceptionName ;
2017-08-12 16:48:01 +00:00
auto scope = DECLARE_CATCH_SCOPE ( vm ) ;
scope . clearException ( ) ;
if ( ! exception ) {
printf ( " Expected uncaught exception with name '%s' but none was thrown \n " , expectedExceptionName . utf8 ( ) . data ( ) ) ;
return false ;
}
2022-10-23 02:55:20 +00:00
JSValue exceptionClass = globalObject - > get ( globalObject , Identifier : : fromString ( vm , expectedExceptionName ) ) ;
2017-08-12 16:48:01 +00:00
if ( ! exceptionClass . isObject ( ) | | scope . exception ( ) ) {
printf ( " Expected uncaught exception with name '%s' but given exception class is not defined \n " , expectedExceptionName . utf8 ( ) . data ( ) ) ;
return false ;
}
2022-10-23 02:55:20 +00:00
bool isInstanceOfExpectedException = jsCast < JSObject * > ( exceptionClass ) - > hasInstance ( globalObject , exception ) ;
2017-08-12 16:48:01 +00:00
if ( scope . exception ( ) ) {
printf ( " Expected uncaught exception with name '%s' but given exception class fails performing hasInstance \n " , expectedExceptionName . utf8 ( ) . data ( ) ) ;
return false ;
}
if ( isInstanceOfExpectedException ) {
2018-01-03 05:16:05 +00:00
if ( options . m_alwaysDumpUncaughtException )
2017-08-12 16:48:01 +00:00
dumpException ( globalObject , exception ) ;
return true ;
}
printf ( " Expected uncaught exception with name '%s' but exception value is not instance of this exception class \n " , expectedExceptionName . utf8 ( ) . data ( ) ) ;
dumpException ( globalObject , exception ) ;
return false ;
}
2022-10-23 02:55:20 +00:00
static void checkException ( GlobalObject * globalObject , bool isLastFile , bool hasException , JSValue value , const CommandLine & options , bool & success )
2017-08-12 16:48:01 +00:00
{
VM & vm = globalObject - > vm ( ) ;
2018-01-03 05:16:05 +00:00
2020-08-29 13:27:11 +00:00
if ( options . m_treatWatchdogExceptionAsSuccess & & value . inherits < TerminatedExecutionError > ( vm ) ) {
2018-01-03 05:16:05 +00:00
ASSERT ( hasException ) ;
return ;
}
if ( ! options . m_uncaughtExceptionName | | ! isLastFile ) {
2017-08-12 16:48:01 +00:00
success = success & & ! hasException ;
2018-01-03 05:16:05 +00:00
if ( options . m_dump & & ! hasException )
2022-10-23 02:55:20 +00:00
printf ( " End: %s \n " , value . toWTFString ( globalObject ) . utf8 ( ) . data ( ) ) ;
2017-08-12 16:48:01 +00:00
if ( hasException )
dumpException ( globalObject , value ) ;
} else
2018-01-03 05:16:05 +00:00
success = success & & checkUncaughtException ( vm , globalObject , ( hasException ) ? value : JSValue ( ) , options ) ;
2017-08-12 16:48:01 +00:00
}
2022-10-23 02:55:20 +00:00
void GlobalObject : : reportUncaughtExceptionAtEventLoop ( JSGlobalObject * globalObject , Exception * exception )
{
auto * global = jsCast < GlobalObject * > ( globalObject ) ;
dumpException ( global , exception - > value ( ) ) ;
bool hideNoReturn = true ;
if ( hideNoReturn )
jscExit ( EXIT_EXCEPTION ) ;
}
2020-08-29 13:27:11 +00:00
static void runWithOptions ( GlobalObject * globalObject , CommandLine & options , bool & success )
2017-08-12 16:48:01 +00:00
{
2018-01-03 05:16:05 +00:00
Vector < Script > & scripts = options . m_scripts ;
2017-08-12 16:48:01 +00:00
String fileName ;
Vector < char > scriptBuffer ;
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_CATCH_SCOPE ( vm ) ;
# if ENABLE(SAMPLING_FLAGS)
SamplingFlags : : start ( ) ;
# endif
for ( size_t i = 0 ; i < scripts . size ( ) ; i + + ) {
JSInternalPromise * promise = nullptr ;
2018-01-03 05:16:05 +00:00
bool isModule = options . m_module | | scripts [ i ] . scriptType = = Script : : ScriptType : : Module ;
2017-08-12 16:48:01 +00:00
if ( scripts [ i ] . codeSource = = Script : : CodeSource : : File ) {
fileName = scripts [ i ] . argument ;
if ( scripts [ i ] . strictMode = = Script : : StrictMode : : Strict )
scriptBuffer . append ( " \" use strict \" ; \n " , strlen ( " \" use strict \" ; \n " ) ) ;
2018-01-03 05:16:05 +00:00
if ( isModule ) {
2022-10-23 02:55:20 +00:00
// If the passed file isn't an absolute path append "./" so the module loader doesn't think this is a bare-name specifier.
fileName = fileName . startsWith ( ' / ' ) ? fileName : makeString ( " ./ " , fileName ) ;
promise = loadAndEvaluateModule ( globalObject , fileName , jsUndefined ( ) , jsUndefined ( ) ) ;
2018-01-03 05:16:05 +00:00
scope . releaseAssertNoException ( ) ;
} else {
2020-08-29 13:27:11 +00:00
if ( ! fetchScriptFromLocalFileSystem ( fileName , scriptBuffer ) ) {
success = false ; // fail early so we can catch missing files
return ;
}
2017-08-12 16:48:01 +00:00
}
} else {
size_t commandLineLength = strlen ( scripts [ i ] . argument ) ;
scriptBuffer . resize ( commandLineLength ) ;
std : : copy ( scripts [ i ] . argument , scripts [ i ] . argument + commandLineLength , scriptBuffer . begin ( ) ) ;
2020-08-29 13:27:11 +00:00
fileName = " [Command Line] " _s ;
2017-08-12 16:48:01 +00:00
}
bool isLastFile = i = = scripts . size ( ) - 1 ;
2022-10-23 02:55:20 +00:00
SourceOrigin sourceOrigin { absolutePath ( fileName ) } ;
2017-08-12 16:48:01 +00:00
if ( isModule ) {
2020-08-29 13:27:11 +00:00
if ( ! promise ) {
// FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
2022-10-23 02:55:20 +00:00
promise = loadAndEvaluateModule ( globalObject , jscSource ( stringFromUTF ( scriptBuffer ) , sourceOrigin , fileName , TextPosition ( ) , SourceProviderSourceType : : Module ) , jsUndefined ( ) ) ;
RETURN_IF_EXCEPTION ( scope , void ( ) ) ;
2020-08-29 13:27:11 +00:00
}
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
JSFunction * fulfillHandler = JSNativeStdFunction : : create ( vm , globalObject , 1 , String ( ) , [ & success , & options , isLastFile ] ( JSGlobalObject * globalObject , CallFrame * callFrame ) {
checkException ( jsCast < GlobalObject * > ( globalObject ) , isLastFile , false , callFrame - > argument ( 0 ) , options , success ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
} ) ;
2022-10-23 02:55:20 +00:00
JSFunction * rejectHandler = JSNativeStdFunction : : create ( vm , globalObject , 1 , String ( ) , [ & success , & options , isLastFile ] ( JSGlobalObject * globalObject , CallFrame * callFrame ) {
checkException ( jsCast < GlobalObject * > ( globalObject ) , isLastFile , true , callFrame - > argument ( 0 ) , options , success ) ;
2017-08-12 16:48:01 +00:00
return JSValue : : encode ( jsUndefined ( ) ) ;
} ) ;
2022-10-23 02:55:20 +00:00
promise - > then ( globalObject , fulfillHandler , rejectHandler ) ;
2018-01-03 05:16:05 +00:00
scope . releaseAssertNoException ( ) ;
2017-08-12 16:48:01 +00:00
vm . drainMicrotasks ( ) ;
} else {
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue returnValue = evaluate ( globalObject , jscSource ( scriptBuffer , sourceOrigin , fileName ) , JSValue ( ) , evaluationException ) ;
2018-01-03 05:16:05 +00:00
scope . assertNoException ( ) ;
2017-08-12 16:48:01 +00:00
if ( evaluationException )
returnValue = evaluationException - > value ( ) ;
2022-10-23 02:55:20 +00:00
checkException ( globalObject , isLastFile , evaluationException , returnValue , options , success ) ;
2017-08-12 16:48:01 +00:00
}
scriptBuffer . clear ( ) ;
scope . clearException ( ) ;
}
# if ENABLE(REGEXP_TRACING)
vm . dumpRegExpTrace ( ) ;
# endif
}
# define RUNNING_FROM_XCODE 0
static void runInteractive ( GlobalObject * globalObject )
{
VM & vm = globalObject - > vm ( ) ;
auto scope = DECLARE_CATCH_SCOPE ( vm ) ;
2022-10-23 02:55:20 +00:00
URL directoryName = currentWorkingDirectory ( ) ;
if ( ! directoryName . isValid ( ) )
2018-01-03 05:16:05 +00:00
return ;
2022-10-23 02:55:20 +00:00
SourceOrigin sourceOrigin ( URL ( directoryName , " ./interpreter " _s ) ) ;
2017-08-12 16:48:01 +00:00
bool shouldQuit = false ;
while ( ! shouldQuit ) {
# if HAVE(READLINE) && !RUNNING_FROM_XCODE
ParserError error ;
String source ;
do {
error = ParserError ( ) ;
char * line = readline ( source . isEmpty ( ) ? interactivePrompt : " ... " ) ;
shouldQuit = ! line ;
if ( ! line )
break ;
2020-08-29 13:27:11 +00:00
source = source + String : : fromUTF8 ( line ) ;
2017-08-12 16:48:01 +00:00
source = source + ' \n ' ;
2020-08-29 13:27:11 +00:00
checkSyntax ( vm , jscSource ( source , sourceOrigin ) , error ) ;
2017-08-12 16:48:01 +00:00
if ( ! line [ 0 ] ) {
free ( line ) ;
break ;
}
add_history ( line ) ;
free ( line ) ;
} while ( error . syntaxErrorType ( ) = = ParserError : : SyntaxErrorRecoverable ) ;
if ( error . isValid ( ) ) {
printf ( " %s:%d \n " , error . message ( ) . utf8 ( ) . data ( ) , error . line ( ) ) ;
continue ;
}
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue returnValue = evaluate ( globalObject , jscSource ( source , sourceOrigin ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
# else
printf ( " %s " , interactivePrompt ) ;
Vector < char , 256 > line ;
int c ;
while ( ( c = getchar ( ) ) ! = EOF ) {
// FIXME: Should we also break on \r?
if ( c = = ' \n ' )
break ;
line . append ( c ) ;
}
if ( line . isEmpty ( ) )
break ;
NakedPtr < Exception > evaluationException ;
2022-10-23 02:55:20 +00:00
JSValue returnValue = evaluate ( globalObject , jscSource ( line , sourceOrigin , sourceOrigin . string ( ) ) , JSValue ( ) , evaluationException ) ;
2017-08-12 16:48:01 +00:00
# endif
2022-10-23 02:55:20 +00:00
Expected < CString , UTF8ConversionError > utf8 ;
if ( evaluationException ) {
fputs ( " Exception: " , stdout ) ;
utf8 = evaluationException - > value ( ) . toWTFString ( globalObject ) . tryGetUtf8 ( ) ;
} else
utf8 = returnValue . toWTFString ( globalObject ) . tryGetUtf8 ( ) ;
CString result ;
if ( utf8 )
result = utf8 . value ( ) ;
else if ( utf8 . error ( ) = = UTF8ConversionError : : OutOfMemory )
result = " OutOfMemory while processing string " ;
2017-08-12 16:48:01 +00:00
else
2022-10-23 02:55:20 +00:00
result = " Error while processing string " ;
fwrite ( result . data ( ) , sizeof ( char ) , result . length ( ) , stdout ) ;
putchar ( ' \n ' ) ;
2017-08-12 16:48:01 +00:00
scope . clearException ( ) ;
2020-08-29 13:27:11 +00:00
vm . drainMicrotasks ( ) ;
2017-08-12 16:48:01 +00:00
}
printf ( " \n " ) ;
}
static NO_RETURN void printUsageStatement ( bool help = false )
{
fprintf ( stderr , " Usage: jsc [options] [files] [-- arguments] \n " ) ;
fprintf ( stderr , " -d Dumps bytecode (debug builds only) \n " ) ;
fprintf ( stderr , " -e Evaluate argument as script code \n " ) ;
fprintf ( stderr , " -f Specifies a source file (deprecated) \n " ) ;
fprintf ( stderr , " -h|--help Prints this help message \n " ) ;
fprintf ( stderr , " -i Enables interactive mode (default if no files are specified) \n " ) ;
fprintf ( stderr , " -m Execute as a module \n " ) ;
2022-10-23 02:55:20 +00:00
# if OS(UNIX)
fprintf ( stderr , " -s Installs signal handlers that exit on a crash (Unix platforms only, lldb will not work with this option) \n " ) ;
2017-08-12 16:48:01 +00:00
# endif
fprintf ( stderr , " -p <file> Outputs profiling data to a file \n " ) ;
fprintf ( stderr , " -x Output exit code before terminating \n " ) ;
fprintf ( stderr , " \n " ) ;
fprintf ( stderr , " --sample Collects and outputs sampling profiler data \n " ) ;
fprintf ( stderr , " --test262-async Check that some script calls the print function with the string 'Test262:AsyncTestComplete' \n " ) ;
fprintf ( stderr , " --strict-file=<file> Parse the given file as if it were in strict mode (this option may be passed more than once) \n " ) ;
fprintf ( stderr , " --module-file=<file> Parse and evaluate the given file as module (this option may be passed more than once) \n " ) ;
fprintf ( stderr , " --exception=<name> Check the last script exits with an uncaught exception with the specified name \n " ) ;
2018-01-03 05:16:05 +00:00
fprintf ( stderr , " --watchdog-exception-ok Uncaught watchdog exceptions exit with success \n " ) ;
2017-08-12 16:48:01 +00:00
fprintf ( stderr , " --dumpException Dump uncaught exception text \n " ) ;
2020-08-29 13:27:11 +00:00
fprintf ( stderr , " --footprint Dump memory footprint after done executing \n " ) ;
2017-08-12 16:48:01 +00:00
fprintf ( stderr , " --options Dumps all JSC VM options and exits \n " ) ;
fprintf ( stderr , " --dumpOptions Dumps all non-default JSC VM options before continuing \n " ) ;
fprintf ( stderr , " --<jsc VM option>=<value> Sets the specified JSC VM option \n " ) ;
2020-08-29 13:27:11 +00:00
fprintf ( stderr , " --destroy-vm Destroy VM before exiting \n " ) ;
2022-10-23 02:55:20 +00:00
fprintf ( stderr , " --can-block-is-false Make main thread's Atomics.wait throw \n " ) ;
2020-08-29 13:27:11 +00:00
fprintf ( stderr , " \n " ) ;
fprintf ( stderr , " Files with a .mjs extension will always be evaluated as modules. \n " ) ;
2017-08-12 16:48:01 +00:00
fprintf ( stderr , " \n " ) ;
jscExit ( help ? EXIT_SUCCESS : EXIT_FAILURE ) ;
}
2020-08-29 13:27:11 +00:00
static bool isMJSFile ( char * filename )
{
filename = strrchr ( filename , ' . ' ) ;
if ( filename )
return ! strcmp ( filename , " .mjs " ) ;
return false ;
}
2017-08-12 16:48:01 +00:00
void CommandLine : : parseArguments ( int argc , char * * argv )
{
2022-10-23 02:55:20 +00:00
Options : : AllowUnfinalizedAccessScope scope ;
2017-08-12 16:48:01 +00:00
Options : : initialize ( ) ;
2022-10-23 02:55:20 +00:00
Options : : useSharedArrayBuffer ( ) = true ;
Options : : useAtMethod ( ) = true ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
# if PLATFORM(IOS_FAMILY)
Options : : crashIfCantAllocateJITMemory ( ) = true ;
# endif
2020-08-29 13:27:11 +00:00
if ( Options : : dumpOptions ( ) ) {
printf ( " Command line: " ) ;
# if PLATFORM(COCOA)
for ( char * * envp = * _NSGetEnviron ( ) ; * envp ; envp + + ) {
const char * env = * envp ;
if ( ! strncmp ( " JSC_ " , env , 4 ) )
printf ( " %s " , env ) ;
}
# endif // PLATFORM(COCOA)
for ( int i = 0 ; i < argc ; + + i )
printf ( " %s " , argv [ i ] ) ;
printf ( " \n " ) ;
}
2017-08-12 16:48:01 +00:00
int i = 1 ;
JSC : : Options : : DumpLevel dumpOptionsLevel = JSC : : Options : : DumpLevel : : None ;
bool needToExit = false ;
bool hasBadJSCOptions = false ;
for ( ; i < argc ; + + i ) {
const char * arg = argv [ i ] ;
if ( ! strcmp ( arg , " -f " ) ) {
if ( + + i = = argc )
printUsageStatement ( ) ;
m_scripts . append ( Script ( Script : : StrictMode : : Sloppy , Script : : CodeSource : : File , Script : : ScriptType : : Script , argv [ i ] ) ) ;
continue ;
}
if ( ! strcmp ( arg , " -e " ) ) {
if ( + + i = = argc )
printUsageStatement ( ) ;
m_scripts . append ( Script ( Script : : StrictMode : : Sloppy , Script : : CodeSource : : CommandLine , Script : : ScriptType : : Script , argv [ i ] ) ) ;
continue ;
}
if ( ! strcmp ( arg , " -i " ) ) {
m_interactive = true ;
continue ;
}
if ( ! strcmp ( arg , " -d " ) ) {
m_dump = true ;
continue ;
}
if ( ! strcmp ( arg , " -p " ) ) {
if ( + + i = = argc )
printUsageStatement ( ) ;
m_profile = true ;
m_profilerOutput = argv [ i ] ;
continue ;
}
if ( ! strcmp ( arg , " -m " ) ) {
m_module = true ;
continue ;
}
if ( ! strcmp ( arg , " -s " ) ) {
2022-10-23 02:55:20 +00:00
# if OS(UNIX)
SignalAction ( * exit ) ( Signal , SigInfo & , PlatformRegisters & ) = [ ] ( Signal , SigInfo & , PlatformRegisters & ) {
dataLogLn ( " Signal handler hit. Exiting with status 0 " ) ;
_exit ( 0 ) ;
return SignalAction : : ForceDefault ;
} ;
addSignalHandler ( Signal : : IllegalInstruction , SignalHandler ( exit ) ) ;
addSignalHandler ( Signal : : AccessFault , SignalHandler ( exit ) ) ;
addSignalHandler ( Signal : : FloatingPoint , SignalHandler ( exit ) ) ;
// once we do this lldb won't work anymore because we will exit on any breakpoints it sets.
addSignalHandler ( Signal : : Breakpoint , SignalHandler ( exit ) ) ;
activateSignalHandlersFor ( Signal : : IllegalInstruction ) ;
activateSignalHandlersFor ( Signal : : AccessFault ) ;
activateSignalHandlersFor ( Signal : : FloatingPoint ) ;
activateSignalHandlersFor ( Signal : : Breakpoint ) ;
# if !OS(DARWIN)
addSignalHandler ( Signal : : Abort , SignalHandler ( exit ) ) ;
activateSignalHandlersFor ( Signal : : Abort ) ;
# endif
2017-08-12 16:48:01 +00:00
# endif
continue ;
}
if ( ! strcmp ( arg , " -x " ) ) {
m_exitCode = true ;
continue ;
}
if ( ! strcmp ( arg , " -- " ) ) {
+ + i ;
break ;
}
if ( ! strcmp ( arg , " -h " ) | | ! strcmp ( arg , " --help " ) )
printUsageStatement ( true ) ;
if ( ! strcmp ( arg , " --options " ) ) {
dumpOptionsLevel = JSC : : Options : : DumpLevel : : Verbose ;
needToExit = true ;
continue ;
}
if ( ! strcmp ( arg , " --dumpOptions " ) ) {
dumpOptionsLevel = JSC : : Options : : DumpLevel : : Overridden ;
continue ;
}
if ( ! strcmp ( arg , " --sample " ) ) {
JSC : : Options : : useSamplingProfiler ( ) = true ;
JSC : : Options : : collectSamplingProfilerDataForJSCShell ( ) = true ;
m_dumpSamplingProfilerData = true ;
continue ;
}
2020-08-29 13:27:11 +00:00
if ( ! strcmp ( arg , " --destroy-vm " ) ) {
m_destroyVM = true ;
continue ;
}
2022-10-23 02:55:20 +00:00
if ( ! strcmp ( arg , " --can-block-is-false " ) ) {
m_canBlockIsFalse = true ;
continue ;
}
if ( ! strcmp ( arg , " --disableOptionsFreezingForTesting " ) ) {
Config : : disableFreezingForTesting ( ) ;
continue ;
}
2017-08-12 16:48:01 +00:00
static const char * timeoutMultiplierOptStr = " --timeoutMultiplier= " ;
static const unsigned timeoutMultiplierOptStrLength = strlen ( timeoutMultiplierOptStr ) ;
if ( ! strncmp ( arg , timeoutMultiplierOptStr , timeoutMultiplierOptStrLength ) ) {
const char * valueStr = & arg [ timeoutMultiplierOptStrLength ] ;
if ( sscanf ( valueStr , " %lf " , & s_timeoutMultiplier ) ! = 1 )
dataLog ( " WARNING: --timeoutMultiplier= " , valueStr , " is invalid. Expects a numeric ratio. \n " ) ;
continue ;
}
if ( ! strcmp ( arg , " --test262-async " ) ) {
2018-01-03 05:16:05 +00:00
asyncTestExpectedPasses + + ;
2017-08-12 16:48:01 +00:00
continue ;
}
if ( ! strcmp ( arg , " --remote-debug " ) ) {
m_enableRemoteDebugging = true ;
continue ;
}
static const unsigned strictFileStrLength = strlen ( " --strict-file= " ) ;
if ( ! strncmp ( arg , " --strict-file= " , strictFileStrLength ) ) {
m_scripts . append ( Script ( Script : : StrictMode : : Strict , Script : : CodeSource : : File , Script : : ScriptType : : Script , argv [ i ] + strictFileStrLength ) ) ;
continue ;
}
static const unsigned moduleFileStrLength = strlen ( " --module-file= " ) ;
if ( ! strncmp ( arg , " --module-file= " , moduleFileStrLength ) ) {
m_scripts . append ( Script ( Script : : StrictMode : : Sloppy , Script : : CodeSource : : File , Script : : ScriptType : : Module , argv [ i ] + moduleFileStrLength ) ) ;
continue ;
}
if ( ! strcmp ( arg , " --dumpException " ) ) {
m_alwaysDumpUncaughtException = true ;
continue ;
}
2020-08-29 13:27:11 +00:00
if ( ! strcmp ( arg , " --footprint " ) ) {
m_dumpMemoryFootprint = true ;
continue ;
}
2017-08-12 16:48:01 +00:00
static const unsigned exceptionStrLength = strlen ( " --exception= " ) ;
if ( ! strncmp ( arg , " --exception= " , exceptionStrLength ) ) {
m_uncaughtExceptionName = String ( arg + exceptionStrLength ) ;
continue ;
}
2018-01-03 05:16:05 +00:00
if ( ! strcmp ( arg , " --watchdog-exception-ok " ) ) {
m_treatWatchdogExceptionAsSuccess = true ;
continue ;
}
2017-08-12 16:48:01 +00:00
// See if the -- option is a JSC VM option.
if ( strstr ( arg , " -- " ) = = arg ) {
if ( ! JSC : : Options : : setOption ( & arg [ 2 ] ) ) {
hasBadJSCOptions = true ;
dataLog ( " ERROR: invalid option: " , arg , " \n " ) ;
}
continue ;
}
// This arg is not recognized by the VM nor by jsc. Pass it on to the
// script.
2020-08-29 13:27:11 +00:00
Script : : ScriptType scriptType = isMJSFile ( argv [ i ] ) ? Script : : ScriptType : : Module : Script : : ScriptType : : Script ;
m_scripts . append ( Script ( Script : : StrictMode : : Sloppy , Script : : CodeSource : : File , scriptType , argv [ i ] ) ) ;
2017-08-12 16:48:01 +00:00
}
if ( hasBadJSCOptions & & JSC : : Options : : validateOptions ( ) )
CRASH ( ) ;
if ( m_scripts . isEmpty ( ) )
m_interactive = true ;
for ( ; i < argc ; + + i )
m_arguments . append ( argv [ i ] ) ;
if ( dumpOptionsLevel ! = JSC : : Options : : DumpLevel : : None ) {
const char * optionsTitle = ( dumpOptionsLevel = = JSC : : Options : : DumpLevel : : Overridden )
? " Modified JSC runtime options: "
: " All JSC runtime options: " ;
JSC : : Options : : dumpAllOptions ( stderr , dumpOptionsLevel , optionsTitle ) ;
}
JSC : : Options : : ensureOptionsAreCoherent ( ) ;
if ( needToExit )
jscExit ( EXIT_SUCCESS ) ;
}
template < typename Func >
2020-08-29 13:27:11 +00:00
int runJSC ( const CommandLine & options , bool isWorker , const Func & func )
2017-08-12 16:48:01 +00:00
{
Worker worker ( Workers : : singleton ( ) ) ;
VM & vm = VM : : create ( LargeHeap ) . leakRef ( ) ;
2022-10-23 02:55:20 +00:00
if ( ! isWorker & & options . m_canBlockIsFalse )
vm . m_typedArrayController = adoptRef ( new JSC : : SimpleTypedArrayController ( false ) ) ;
# if ENABLE(WEBASSEMBLY)
Wasm : : enableFastMemory ( ) ;
# endif
2017-08-12 16:48:01 +00:00
int result ;
2020-08-29 13:27:11 +00:00
bool success = true ;
GlobalObject * globalObject = nullptr ;
2018-01-03 05:16:05 +00:00
{
JSLockHolder locker ( vm ) ;
2017-08-12 16:48:01 +00:00
2022-10-23 02:55:20 +00:00
startTimeoutThreadIfNeeded ( vm ) ;
2018-01-03 05:16:05 +00:00
if ( options . m_profile & & ! vm . m_perBytecodeProfiler )
2022-10-23 02:55:20 +00:00
vm . m_perBytecodeProfiler = makeUnique < Profiler : : Database > ( vm ) ;
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
globalObject = GlobalObject : : create ( vm , GlobalObject : : createStructure ( vm , jsNull ( ) ) , options . m_arguments ) ;
2018-01-03 05:16:05 +00:00
globalObject - > setRemoteDebuggingEnabled ( options . m_enableRemoteDebugging ) ;
2020-08-29 13:27:11 +00:00
func ( vm , globalObject , success ) ;
2018-01-03 05:16:05 +00:00
vm . drainMicrotasks ( ) ;
}
2022-10-23 02:55:20 +00:00
vm . deferredWorkTimer - > runRunLoop ( ) ;
2020-08-29 13:27:11 +00:00
{
JSLockHolder locker ( vm ) ;
if ( options . m_interactive & & success )
runInteractive ( globalObject ) ;
}
2017-08-12 16:48:01 +00:00
2018-01-03 05:16:05 +00:00
result = success & & ( asyncTestExpectedPasses = = asyncTestPasses ) ? 0 : 3 ;
if ( options . m_exitCode ) {
printf ( " jsc exiting %d " , result ) ;
if ( asyncTestExpectedPasses ! = asyncTestPasses )
printf ( " because expected: %d async test passes but got: %d async test passes " , asyncTestExpectedPasses , asyncTestPasses ) ;
printf ( " \n " ) ;
}
2017-08-12 16:48:01 +00:00
if ( options . m_profile ) {
2018-01-03 05:16:05 +00:00
JSLockHolder locker ( vm ) ;
2017-08-12 16:48:01 +00:00
if ( ! vm . m_perBytecodeProfiler - > save ( options . m_profilerOutput . utf8 ( ) . data ( ) ) )
fprintf ( stderr , " could not save profiler output. \n " ) ;
}
# if ENABLE(JIT)
2018-01-03 05:16:05 +00:00
{
JSLockHolder locker ( vm ) ;
if ( Options : : useExceptionFuzz ( ) )
printf ( " JSC EXCEPTION FUZZ: encountered %u checks. \n " , numberOfExceptionFuzzChecks ( ) ) ;
bool fireAtEnabled =
Options : : fireExecutableAllocationFuzzAt ( ) | | Options : : fireExecutableAllocationFuzzAtOrAfter ( ) ;
if ( Options : : useExecutableAllocationFuzz ( ) & & ( ! fireAtEnabled | | Options : : verboseExecutableAllocationFuzz ( ) ) )
printf ( " JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks. \n " , numberOfExecutableAllocationFuzzChecks ( ) ) ;
2022-10-23 02:55:20 +00:00
if ( Options : : useOSRExitFuzz ( ) & & Options : : verboseOSRExitFuzz ( ) ) {
2018-01-03 05:16:05 +00:00
printf ( " JSC OSR EXIT FUZZ: encountered %u static checks. \n " , numberOfStaticOSRExitFuzzChecks ( ) ) ;
printf ( " JSC OSR EXIT FUZZ: encountered %u dynamic checks. \n " , numberOfOSRExitFuzzChecks ( ) ) ;
}
auto compileTimeStats = JIT : : compileTimeStats ( ) ;
Vector < CString > compileTimeKeys ;
for ( auto & entry : compileTimeStats )
compileTimeKeys . append ( entry . key ) ;
std : : sort ( compileTimeKeys . begin ( ) , compileTimeKeys . end ( ) ) ;
2022-10-23 02:55:20 +00:00
for ( const CString & key : compileTimeKeys ) {
if ( key . data ( ) )
printf ( " %40s: %.3lf ms \n " , key . data ( ) , compileTimeStats . get ( key ) . milliseconds ( ) ) ;
}
if ( Options : : reportTotalPhaseTimes ( ) )
logTotalPhaseTimes ( ) ;
2018-01-03 05:16:05 +00:00
}
2017-08-12 16:48:01 +00:00
# endif
if ( Options : : gcAtEnd ( ) ) {
// We need to hold the API lock to do a GC.
JSLockHolder locker ( & vm ) ;
2018-01-03 05:16:05 +00:00
vm . heap . collectNow ( Sync , CollectionScope : : Full ) ;
2017-08-12 16:48:01 +00:00
}
if ( options . m_dumpSamplingProfilerData ) {
# if ENABLE(SAMPLING_PROFILER)
JSLockHolder locker ( & vm ) ;
vm . samplingProfiler ( ) - > reportTopFunctions ( ) ;
vm . samplingProfiler ( ) - > reportTopBytecodes ( ) ;
# else
dataLog ( " Sampling profiler is not enabled on this platform \n " ) ;
# endif
}
2020-08-29 13:27:11 +00:00
vm . codeCache ( ) - > write ( vm ) ;
if ( options . m_destroyVM | | isWorker ) {
2018-01-03 05:16:05 +00:00
JSLockHolder locker ( vm ) ;
// This is needed because we don't want the worker's main
// thread to die before its compilation threads finish.
vm . deref ( ) ;
}
2017-08-12 16:48:01 +00:00
return result ;
}
2022-10-23 02:55:20 +00:00
# if ENABLE(JIT_OPERATION_VALIDATION)
extern const uintptr_t startOfJITOperationsInShell __asm ( " section$start$__DATA_CONST$__jsc_ops " ) ;
extern const uintptr_t endOfJITOperationsInShell __asm ( " section$end$__DATA_CONST$__jsc_ops " ) ;
# endif
2017-08-12 16:48:01 +00:00
int jscmain ( int argc , char * * argv )
{
// Need to override and enable restricted options before we start parsing options below.
2022-10-23 02:55:20 +00:00
Config : : enableRestrictedOptions ( ) ;
WTF : : initializeMainThread ( ) ;
2017-08-12 16:48:01 +00:00
// Note that the options parsing can affect VM creation, and thus
// comes first.
CommandLine options ( argc , argv ) ;
2022-10-23 02:55:20 +00:00
{
Options : : AllowUnfinalizedAccessScope scope ;
processConfigFile ( Options : : configFile ( ) , " jsc " ) ;
if ( options . m_dump )
Options : : dumpGeneratedBytecodes ( ) = true ;
}
2018-01-03 05:16:05 +00:00
2022-10-23 02:55:20 +00:00
JSC : : initialize ( ) ;
# if ENABLE(JIT_OPERATION_VALIDATION)
JSC : : JITOperationList : : populatePointersInEmbedder ( & startOfJITOperationsInShell , & endOfJITOperationsInShell ) ;
2018-01-03 05:16:05 +00:00
# endif
2022-10-23 02:55:20 +00:00
initializeTimeoutIfNeeded ( ) ;
# if OS(DARWIN) || OS(LINUX)
startMemoryMonitoringThreadIfNeeded ( ) ;
# endif
if ( Options : : useSuperSampler ( ) )
enableSuperSampler ( ) ;
bool gigacageDisableRequested = false ;
# if GIGACAGE_ENABLED && !COMPILER(MSVC)
if ( char * gigacageEnabled = getenv ( " GIGACAGE_ENABLED " ) ) {
if ( ! strcasecmp ( gigacageEnabled , " no " ) | | ! strcasecmp ( gigacageEnabled , " false " ) | | ! strcasecmp ( gigacageEnabled , " 0 " ) )
gigacageDisableRequested = true ;
}
# endif
if ( ! gigacageDisableRequested )
Gigacage : : forbidDisablingPrimitiveGigacage ( ) ;
2017-08-12 16:48:01 +00:00
2020-08-29 13:27:11 +00:00
# if PLATFORM(COCOA)
auto & memoryPressureHandler = MemoryPressureHandler : : singleton ( ) ;
{
dispatch_queue_t queue = dispatch_queue_create ( " jsc shell memory pressure handler " , DISPATCH_QUEUE_SERIAL ) ;
memoryPressureHandler . setDispatchQueue ( queue ) ;
dispatch_release ( queue ) ;
}
Box < Critical > memoryPressureCriticalState = Box < Critical > : : create ( Critical : : No ) ;
Box < Synchronous > memoryPressureSynchronousState = Box < Synchronous > : : create ( Synchronous : : No ) ;
memoryPressureHandler . setLowMemoryHandler ( [ = ] ( Critical critical , Synchronous synchronous ) {
2022-10-23 02:55:20 +00:00
crashIfExceedingMemoryLimit ( ) ;
2020-08-29 13:27:11 +00:00
// We set these racily with respect to reading them from the JS execution thread.
* memoryPressureCriticalState = critical ;
* memoryPressureSynchronousState = synchronous ;
} ) ;
memoryPressureHandler . setShouldLogMemoryMemoryPressureEvents ( false ) ;
memoryPressureHandler . install ( ) ;
auto onEachMicrotaskTick = [ & ] ( VM & vm ) {
if ( * memoryPressureCriticalState = = Critical : : No )
return ;
* memoryPressureCriticalState = Critical : : No ;
bool isSynchronous = * memoryPressureSynchronousState = = Synchronous : : Yes ;
WTF : : releaseFastMallocFreeMemory ( ) ;
vm . deleteAllCode ( DeleteAllCodeIfNotCollecting ) ;
if ( ! vm . heap . isCurrentThreadBusy ( ) ) {
if ( isSynchronous ) {
vm . heap . collectNow ( Sync , CollectionScope : : Full ) ;
WTF : : releaseFastMallocFreeMemory ( ) ;
} else
vm . heap . collectNowFullIfNotDoneRecently ( Async ) ;
}
} ;
# endif
int result = runJSC (
2018-01-03 05:16:05 +00:00
options , false ,
2020-08-29 13:27:11 +00:00
[ & ] ( VM & vm , GlobalObject * globalObject , bool & success ) {
UNUSED_PARAM ( vm ) ;
# if PLATFORM(COCOA)
vm . setOnEachMicrotaskTick ( WTFMove ( onEachMicrotaskTick ) ) ;
# endif
runWithOptions ( globalObject , options , success ) ;
2017-08-12 16:48:01 +00:00
} ) ;
printSuperSamplerState ( ) ;
2020-08-29 13:27:11 +00:00
if ( options . m_dumpMemoryFootprint ) {
MemoryFootprint footprint = MemoryFootprint : : now ( ) ;
printf ( " Memory Footprint: \n Current Footprint: % " PRIu64 " \n Peak Footprint: % " PRIu64 " \n " , footprint . current , footprint . peak ) ;
}
2017-08-12 16:48:01 +00:00
return result ;
}
# if OS(WINDOWS)
extern " C " __declspec ( dllexport ) int WINAPI dllLauncherEntryPoint ( int argc , const char * argv [ ] )
{
return main ( argc , const_cast < char * * > ( argv ) ) ;
}
# endif