mirror of
https://github.com/denoland/deno
synced 2024-08-24 18:47:06 +00:00
Source map support (#429)
This change increases size: out/debug/obj/libdeno/from_snapshot.o 19M -> 34M out/release/deno 32M -> 47M
This commit is contained in:
parent
e30bdb71aa
commit
c7c6203e61
1
BUILD.gn
1
BUILD.gn
|
@ -264,6 +264,7 @@ rust_flatbuffer("msg_rs") {
|
|||
# Generates $target_gen_dir/snapshot_deno.cc
|
||||
create_snapshot("deno") {
|
||||
js = "$target_gen_dir/bundle/main.js"
|
||||
source_map = "$target_gen_dir/bundle/main.js.map"
|
||||
deps = [
|
||||
":bundle",
|
||||
]
|
||||
|
|
|
@ -32,13 +32,14 @@ template("create_snapshot") {
|
|||
inputs = [
|
||||
invoker.js,
|
||||
]
|
||||
if (defined(invoker.source_map)) {
|
||||
inputs += [ invoker.source_map ]
|
||||
}
|
||||
outputs = [
|
||||
snapshot_out_bin,
|
||||
]
|
||||
args = [
|
||||
rebase_path(snapshot_out_bin, root_build_dir),
|
||||
rebase_path(invoker.js, root_build_dir),
|
||||
]
|
||||
args = rebase_path(outputs, root_build_dir) +
|
||||
rebase_path(inputs, root_build_dir)
|
||||
|
||||
# To debug snapshotting problems:
|
||||
# args += ["--trace-serializer"]
|
||||
|
|
9
js/lib.deno.d.ts
vendored
9
js/lib.deno.d.ts
vendored
|
@ -27,10 +27,15 @@ declare class Console {
|
|||
|
||||
interface Window {
|
||||
console: Console;
|
||||
mainSource: string; // TODO(ry) This shouldn't be global.
|
||||
// TODO(ry) These shouldn't be global.
|
||||
mainSource: string;
|
||||
setMainSourceMap(sm: string): void;
|
||||
}
|
||||
|
||||
// Globals in the runtime environment
|
||||
declare let console: Console;
|
||||
declare let mainSource: string; // TODO(ry) This shouldn't be global.
|
||||
declare const window: Window;
|
||||
|
||||
// TODO(ry) These shouldn't be global.
|
||||
declare let mainSource: string;
|
||||
declare function setMainSourceMap(sm: string): void;
|
||||
|
|
|
@ -20,6 +20,8 @@ function startMsg(cmdId: number): Uint8Array {
|
|||
|
||||
/* tslint:disable-next-line:no-default-export */
|
||||
export default function denoMain() {
|
||||
runtime.setup();
|
||||
|
||||
// First we send an empty "Start" message to let the privlaged side know we
|
||||
// are ready. The response should be a "StartRes" message containing the CLI
|
||||
// argv and other info.
|
||||
|
|
|
@ -12,7 +12,7 @@ import * as util from "./util";
|
|||
import { log } from "./util";
|
||||
import { assetSourceCode } from "./assets";
|
||||
import * as os from "./os";
|
||||
//import * as sourceMaps from "./v8_source_maps";
|
||||
import * as sourceMaps from "./v8_source_maps";
|
||||
import { window, globalEval } from "./globals";
|
||||
//import * as deno from "./deno";
|
||||
|
||||
|
@ -39,26 +39,39 @@ window.onerror = (
|
|||
os.exit(1);
|
||||
};
|
||||
|
||||
/*
|
||||
export function setup(mainJs: string, mainMap: string): void {
|
||||
// This is called during snapshot creation with the contents of
|
||||
// out/debug/gen/bundle/main.js.map.
|
||||
import { RawSourceMap } from "source-map";
|
||||
let mainSourceMap: RawSourceMap = null;
|
||||
function setMainSourceMap(rawSourceMap: RawSourceMap) {
|
||||
util.assert(Number(rawSourceMap.version) === 3);
|
||||
mainSourceMap = rawSourceMap;
|
||||
}
|
||||
window["setMainSourceMap"] = setMainSourceMap;
|
||||
|
||||
export function setup(): void {
|
||||
sourceMaps.install({
|
||||
installPrepareStackTrace: true,
|
||||
getGeneratedContents: (filename: string): string => {
|
||||
if (filename === "/main.js") {
|
||||
return mainJs;
|
||||
} else if (filename === "/main.map") {
|
||||
return mainMap;
|
||||
getGeneratedContents: (filename: string): string | RawSourceMap => {
|
||||
util.log("getGeneratedContents", filename);
|
||||
if (filename === "gen/bundle/main.js") {
|
||||
util.assert(window["mainSource"].length > 0);
|
||||
return window["mainSource"];
|
||||
} else if (filename === "main.js.map") {
|
||||
return mainSourceMap;
|
||||
} else if (filename === "deno_main.js") {
|
||||
return "";
|
||||
} else {
|
||||
const mod = FileModule.load(filename);
|
||||
if (!mod) {
|
||||
console.error("getGeneratedContents cannot find", filename);
|
||||
util.log("getGeneratedContents cannot find", filename);
|
||||
return null;
|
||||
}
|
||||
return mod.outputCode;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
// This class represents a module. We call it FileModule to make it explicit
|
||||
// that each module represents a single file.
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
// Copyright 2014 Evan Wallace
|
||||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||
// Originated from source-map-support but has been heavily modified for deno.
|
||||
|
||||
// Because NodeJS.CallSite and Error.prepareStackTrace are used we add a
|
||||
// dependency on the Node types.
|
||||
// TODO(ry) Ideally this triple slash directive should be removed as we only
|
||||
// need CallSite and Error.prepareStackTrace but nothing else.
|
||||
/// <reference types="node" />
|
||||
|
||||
import { SourceMapConsumer, MappedPosition } from "source-map";
|
||||
import { RawSourceMap } from "source-map";
|
||||
import * as base64 from "base64-js";
|
||||
import { arrayToStr } from "./util";
|
||||
|
||||
|
@ -24,7 +32,7 @@ interface Position {
|
|||
line: number;
|
||||
}
|
||||
|
||||
type GetGeneratedContentsCallback = (fileName: string) => string;
|
||||
type GetGeneratedContentsCallback = (fileName: string) => string | RawSourceMap;
|
||||
|
||||
let getGeneratedContents: GetGeneratedContentsCallback;
|
||||
|
||||
|
@ -190,13 +198,16 @@ function loadConsumer(source: string): SourceMapConsumer {
|
|||
if (!code) {
|
||||
return null;
|
||||
}
|
||||
if (typeof code !== "string") {
|
||||
throw new Error("expected string");
|
||||
}
|
||||
|
||||
let sourceMappingURL = retrieveSourceMapURL(code);
|
||||
if (!sourceMappingURL) {
|
||||
throw Error("No source map?");
|
||||
}
|
||||
|
||||
let sourceMapData: string;
|
||||
let sourceMapData: string | RawSourceMap;
|
||||
if (reSourceMap.test(sourceMappingURL)) {
|
||||
// Support source map URL as a data url
|
||||
const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1);
|
||||
|
@ -209,8 +220,11 @@ function loadConsumer(source: string): SourceMapConsumer {
|
|||
sourceMapData = getGeneratedContents(sourceMappingURL);
|
||||
}
|
||||
|
||||
const rawSourceMap =
|
||||
typeof sourceMapData === "string"
|
||||
? JSON.parse(sourceMapData)
|
||||
: sourceMapData;
|
||||
//console.log("sourceMapData", sourceMapData);
|
||||
const rawSourceMap = JSON.parse(sourceMapData);
|
||||
consumer = new SourceMapConsumer(rawSourceMap);
|
||||
consumers.set(source, consumer);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,8 @@ bool Execute(v8::Local<v8::Context> context, const char* js_filename,
|
|||
}
|
||||
|
||||
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||
const char* js_filename, const char* js_source) {
|
||||
const char* js_filename, const std::string& js_source,
|
||||
const std::string* source_map) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
|
@ -293,11 +294,19 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|||
|
||||
skip_onerror = true;
|
||||
{
|
||||
auto source = deno::v8_str(js_source);
|
||||
auto source = deno::v8_str(js_source.c_str());
|
||||
CHECK(global->Set(context, deno::v8_str("mainSource"), source).FromJust());
|
||||
|
||||
bool r = deno::ExecuteV8StringSource(context, js_filename, source);
|
||||
CHECK(r);
|
||||
|
||||
if (source_map != nullptr) {
|
||||
CHECK_GT(source_map->length(), 1u);
|
||||
std::string set_source_map = "setMainSourceMap( " + *source_map + " )";
|
||||
CHECK_GT(set_source_map.length(), source_map->length());
|
||||
r = deno::Execute(context, "set_source_map.js", set_source_map.c_str());
|
||||
CHECK(r);
|
||||
}
|
||||
}
|
||||
skip_onerror = false;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ Deno* NewFromFileSystem(void* data, deno_recv_cb cb) {
|
|||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto context = v8::Context::New(isolate);
|
||||
InitializeContext(isolate, context, BUNDLE_LOCATION, js_source.c_str());
|
||||
InitializeContext(isolate, context, BUNDLE_LOCATION, js_source, nullptr);
|
||||
d->context.Reset(d->isolate, context);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ struct deno_s {
|
|||
// TODO(ry) Remove these when we call deno_reply_start from Rust.
|
||||
char** deno_argv();
|
||||
int deno_argc();
|
||||
struct deno_s* deno_from_isolate(v8::Isolate* isolate);
|
||||
}
|
||||
|
||||
namespace deno {
|
||||
|
@ -38,7 +39,8 @@ static intptr_t external_references[] = {reinterpret_cast<intptr_t>(Print),
|
|||
Deno* NewFromSnapshot(void* data, deno_recv_cb cb);
|
||||
|
||||
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||
const char* js_filename, const char* js_source);
|
||||
const char* js_filename, const std::string& js_source,
|
||||
const std::string* source_map);
|
||||
|
||||
void AddIsolate(Deno* d, v8::Isolate* isolate);
|
||||
|
||||
|
|
|
@ -22,14 +22,16 @@ v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
|||
return {payload, size};
|
||||
}
|
||||
|
||||
v8::StartupData MakeSnapshot(const char* js_filename, const char* js_source) {
|
||||
v8::StartupData MakeSnapshot(const char* js_filename,
|
||||
const std::string& js_source,
|
||||
const std::string* source_map) {
|
||||
auto* creator = new v8::SnapshotCreator(external_references);
|
||||
auto* isolate = creator->GetIsolate();
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto context = v8::Context::New(isolate);
|
||||
InitializeContext(isolate, context, js_filename, js_source);
|
||||
InitializeContext(isolate, context, js_filename, js_source, source_map);
|
||||
creator->SetDefaultContext(context, v8::SerializeInternalFieldsCallback(
|
||||
SerializeInternalFields, nullptr));
|
||||
}
|
||||
|
@ -45,18 +47,25 @@ v8::StartupData MakeSnapshot(const char* js_filename, const char* js_source) {
|
|||
int main(int argc, char** argv) {
|
||||
const char* snapshot_out_bin = argv[1];
|
||||
const char* js_fn = argv[2];
|
||||
const char* source_map_fn = argv[3]; // Optional.
|
||||
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
|
||||
CHECK_EQ(argc, 3);
|
||||
CHECK_NE(js_fn, nullptr);
|
||||
CHECK_NE(snapshot_out_bin, nullptr);
|
||||
|
||||
std::string js_source;
|
||||
CHECK(deno::ReadFileToString(js_fn, &js_source));
|
||||
|
||||
std::string source_map;
|
||||
if (source_map_fn != nullptr) {
|
||||
CHECK_EQ(argc, 4);
|
||||
CHECK(deno::ReadFileToString(source_map_fn, &source_map));
|
||||
}
|
||||
|
||||
deno_init();
|
||||
auto snapshot_blob = deno::MakeSnapshot(js_fn, js_source.c_str());
|
||||
auto snapshot_blob = deno::MakeSnapshot(
|
||||
js_fn, js_source, source_map_fn != nullptr ? &source_map : nullptr);
|
||||
std::string snapshot_str(snapshot_blob.data, snapshot_blob.raw_size);
|
||||
|
||||
std::ofstream file_(snapshot_out_bin, std::ios::binary);
|
||||
|
|
7
tests/008_stack_trace.ts
Normal file
7
tests/008_stack_trace.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { throwsError } from "./subdir/mod1.ts";
|
||||
|
||||
function foo() {
|
||||
throwsError();
|
||||
}
|
||||
|
||||
foo();
|
Loading…
Reference in a new issue