aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/modules/BunJSCModule.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/modules/BunJSCModule.h')
-rw-r--r--src/bun.js/modules/BunJSCModule.h60
1 files changed, 59 insertions, 1 deletions
diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h
index d7548dcdf..73823e16e 100644
--- a/src/bun.js/modules/BunJSCModule.h
+++ b/src/bun.js/modules/BunJSCModule.h
@@ -28,14 +28,17 @@
#include "wtf/text/WTFString.h"
#include "Process.h"
-
+#include <JavaScriptCore/SourceProviderCache.h>
#if ENABLE(REMOTE_INSPECTOR)
#include "JavaScriptCore/RemoteInspectorServer.h"
#endif
#include "JSDOMConvertBase.h"
+#include "ZigSourceProvider.h"
#include "mimalloc.h"
+#include "JavaScriptCore/ControlFlowProfiler.h"
+
using namespace JSC;
using namespace WTF;
using namespace WebCore;
@@ -650,6 +653,60 @@ JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject,
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
}
+extern "C" EncodedJSValue ByteRangeMapping__findExecutedLines(
+ JSC::JSGlobalObject *, BunString sourceURL, BasicBlockRange *ranges,
+ size_t len, size_t functionOffset, bool ignoreSourceMap);
+
+JSC_DEFINE_HOST_FUNCTION(functionCodeCoverageForFile,
+ (JSGlobalObject * globalObject,
+ CallFrame *callFrame)) {
+ VM &vm = globalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ String fileName = callFrame->argument(0).toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ bool ignoreSourceMap = callFrame->argument(1).toBoolean(globalObject);
+
+ auto sourceID = Zig::sourceIDForSourceURL(fileName);
+ if (!sourceID) {
+ throwException(globalObject, throwScope,
+ createError(globalObject, "No source for file"_s));
+ return JSValue::encode(jsUndefined());
+ }
+
+ auto basicBlocks =
+ vm.controlFlowProfiler()->getBasicBlocksForSourceIDWithoutFunctionRange(
+ sourceID, vm);
+
+ if (basicBlocks.isEmpty()) {
+ return JSC::JSValue::encode(
+ JSC::constructEmptyArray(globalObject, nullptr, 0));
+ }
+
+ size_t functionStartOffset = basicBlocks.size();
+
+ const Vector<std::tuple<bool, unsigned, unsigned>> &functionRanges =
+ vm.functionHasExecutedCache()->getFunctionRanges(sourceID);
+
+ basicBlocks.reserveCapacity(functionRanges.size() + basicBlocks.size());
+
+ for (const auto &functionRange : functionRanges) {
+ BasicBlockRange range;
+ range.m_hasExecuted = std::get<0>(functionRange);
+ range.m_startOffset = static_cast<int>(std::get<1>(functionRange));
+ range.m_endOffset = static_cast<int>(std::get<2>(functionRange));
+ range.m_executionCount =
+ range.m_hasExecuted
+ ? 1
+ : 0; // This is a hack. We don't actually count this.
+ basicBlocks.append(range);
+ }
+
+ return ByteRangeMapping__findExecutedLines(
+ globalObject, Bun::toString(fileName), basicBlocks.data(),
+ basicBlocks.size(), functionStartOffset, ignoreSourceMap);
+}
+
// clang-format off
/* Source for BunJSCModuleTable.lut.h
@begin BunJSCModuleTable
@@ -718,6 +775,7 @@ DEFINE_NATIVE_MODULE(BunJSC)
putNativeFn(Identifier::fromString(vm, "getProtectedObjects"_s), functionGetProtectedObjects);
putNativeFn(Identifier::fromString(vm, "generateHeapSnapshotForDebugging"_s), functionGenerateHeapSnapshotForDebugging);
putNativeFn(Identifier::fromString(vm, "profile"_s), functionRunProfiler);
+ putNativeFn(Identifier::fromString(vm, "codeCoverageForFile"_s), functionCodeCoverageForFile);
putNativeFn(Identifier::fromString(vm, "setTimeZone"_s), functionSetTimeZone);
putNativeFn(Identifier::fromString(vm, "serialize"_s), functionSerialize);
putNativeFn(Identifier::fromString(vm, "deserialize"_s), functionDeserialize);