1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05: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:
Ryan Dahl 2018-08-02 13:13:32 -04:00 committed by GitHub
parent e30bdb71aa
commit c7c6203e61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 27 deletions

View file

@ -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",
]

View file

@ -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
View file

@ -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;

View file

@ -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.

View file

@ -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.

View 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);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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
View file

@ -0,0 +1,7 @@
import { throwsError } from "./subdir/mod1.ts";
function foo() {
throwsError();
}
foo();