From 51380bf39936e0bcb1cb671bb20e961e1bb18e7d Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 6 Aug 2018 18:37:32 -0400 Subject: [PATCH] Organize libdeno functions. --- js/console.ts | 8 ++++++-- js/deno.ts | 3 ++- js/globals.ts | 27 +++++++++++++++------------ js/lib.globals.d.ts | 16 +--------------- js/main.ts | 4 ++-- js/mock_runtime.js | 36 ++++++++++++++++++------------------ js/os.ts | 7 ++++--- js/runtime.ts | 21 ++++++--------------- js/types.d.ts | 13 +++++++++++++ js/v8_source_maps.ts | 3 +-- src/binding.cc | 30 ++++++++++++++++++++++++------ src/deno_dir.rs | 3 ++- 12 files changed, 94 insertions(+), 77 deletions(-) diff --git a/js/console.ts b/js/console.ts index 1ec727f143..48ecc6e7e1 100644 --- a/js/console.ts +++ b/js/console.ts @@ -97,10 +97,14 @@ function stringifyArgs(args: any[]): string { return out.join(" "); } +type PrintFunc = (x: string) => void; + export class Console { + constructor(private printFunc: PrintFunc) {} + // tslint:disable-next-line:no-any log(...args: any[]): void { - deno.print(stringifyArgs(args)); + this.printFunc(stringifyArgs(args)); } debug = this.log; @@ -108,7 +112,7 @@ export class Console { // tslint:disable-next-line:no-any warn(...args: any[]): void { - deno.print(`ERROR: ${stringifyArgs(args)}`); + this.printFunc(`ERROR: ${stringifyArgs(args)}`); } error = this.warn; diff --git a/js/deno.ts b/js/deno.ts index 9ef533a9ea..f281ebefa5 100644 --- a/js/deno.ts +++ b/js/deno.ts @@ -2,4 +2,5 @@ // Public deno module. // TODO get rid of deno.d.ts // export { pub, sub } from "./dispatch"; -export { readFileSync, writeFileSync } from "./os"; +export { readFileSync } from "./os"; +export { libdeno } from "./globals"; diff --git a/js/globals.ts b/js/globals.ts index 82c9a24c0f..a184cc9a1c 100644 --- a/js/globals.ts +++ b/js/globals.ts @@ -1,22 +1,14 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. import { Console } from "./console"; +import { RawSourceMap } from "./types"; declare global { - type MessageCallback = (msg: Uint8Array) => void; - - interface Deno { - print(text: string): void; - recv(cb: MessageCallback): void; - send(msg: ArrayBufferView): Uint8Array | null; - } - interface Window { console: Console; } const console: Console; - const deno: Readonly; const window: Window; } @@ -28,10 +20,21 @@ declare global { export const globalEval = eval; // A reference to the global object. -// TODO The underscore is because it's conflicting with @types/node. export const window = globalEval("this"); +window.window = window; + +// The libdeno functions are moved so that users can't access them. +type MessageCallback = (msg: Uint8Array) => void; +interface Libdeno { + recv(cb: MessageCallback): void; + send(msg: ArrayBufferView): null | Uint8Array; + print(x: string): void; + mainSource: string; + mainSourceMap: RawSourceMap; +} +export const libdeno = window.libdeno as Libdeno; +window.libdeno = null; -window["window"] = window; // Create a window object. // import "./url"; // import * as timer from "./timers"; @@ -40,7 +43,7 @@ window["window"] = window; // Create a window object. // window["clearTimeout"] = timer.clearTimer; // window["clearInterval"] = timer.clearTimer; -window["console"] = new Console(); +window.console = new Console(libdeno.print); // import { fetch } from "./fetch"; // window["fetch"] = fetch; diff --git a/js/lib.globals.d.ts b/js/lib.globals.d.ts index d11bbe97da..a1526c573c 100644 --- a/js/lib.globals.d.ts +++ b/js/lib.globals.d.ts @@ -1,19 +1,5 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. - -// This file contains the default TypeScript libraries for the runtime - +// This file contains the default TypeScript libraries for the deno runtime. /// - /// - import "gen/js/globals"; - -interface Window { - // TODO(ry) These shouldn't be global. - mainSource: string; - setMainSourceMap(sm: string): void; -} - -// TODO(ry) These shouldn't be global. -declare let mainSource: string; -declare function setMainSourceMap(sm: string): void; diff --git a/js/main.ts b/js/main.ts index 29c4ab4124..1585fd0920 100644 --- a/js/main.ts +++ b/js/main.ts @@ -1,9 +1,9 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. -// tslint:disable-next-line:no-reference import { flatbuffers } from "flatbuffers"; import { deno as fbs } from "gen/msg_generated"; import { assert, log, assignCmdId } from "./util"; import * as runtime from "./runtime"; +import { libdeno } from "./globals"; function startMsg(cmdId: number): Uint8Array { const builder = new flatbuffers.Builder(); @@ -25,7 +25,7 @@ export default function denoMain() { // are ready. The response should be a "StartRes" message containing the CLI // argv and other info. const cmdId = assignCmdId(); - const res = deno.send(startMsg(cmdId)); + const res = libdeno.send(startMsg(cmdId)); // TODO(ry) Remove this conditional once main.rs gets up to speed. if (res == null) { diff --git a/js/mock_runtime.js b/js/mock_runtime.js index 9fe59ae06c..34f78479e2 100644 --- a/js/mock_runtime.js +++ b/js/mock_runtime.js @@ -10,7 +10,7 @@ function assert(cond) { } global.CanCallFunction = () => { - deno.print("Hello world from foo"); + libdeno.print("Hello world from foo"); return "foo"; }; @@ -26,13 +26,13 @@ global.TypedArraySnapshots = () => { }; global.SendSuccess = () => { - deno.recv(msg => { - deno.print("SendSuccess: ok"); + libdeno.recv(msg => { + libdeno.print("SendSuccess: ok"); }); }; global.SendWrongByteLength = () => { - deno.recv(msg => { + libdeno.recv(msg => { assert(msg.byteLength === 3); }); }; @@ -40,15 +40,15 @@ global.SendWrongByteLength = () => { global.RecvReturnEmpty = () => { const m1 = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); const m2 = m1.slice(); - const r1 = deno.send(m1); + const r1 = libdeno.send(m1); assert(r1 == null); - const r2 = deno.send(m2); + const r2 = libdeno.send(m2); assert(r2 == null); }; global.RecvReturnBar = () => { const m = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); - const r = deno.send(m); + const r = libdeno.send(m); assert(r instanceof Uint8Array); assert(r.byteLength === 3); const rstr = String.fromCharCode(...r); @@ -56,10 +56,10 @@ global.RecvReturnBar = () => { }; global.DoubleRecvFails = () => { - // deno.recv is an internal function and should only be called once from the + // libdeno.recv is an internal function and should only be called once from the // runtime. - deno.recv((channel, msg) => assert(false)); - deno.recv((channel, msg) => assert(false)); + libdeno.recv((channel, msg) => assert(false)); + libdeno.recv((channel, msg) => assert(false)); }; global.SendRecvSlice = () => { @@ -70,7 +70,7 @@ global.SendRecvSlice = () => { buf[0] = 100 + i; buf[buf.length - 1] = 100 - i; // On the native side, the slice is shortened by 19 bytes. - buf = deno.send(buf); + buf = libdeno.send(buf); assert(buf.byteOffset === i * 11); assert(buf.byteLength === abLen - i * 30 - 19); assert(buf.buffer.byteLength == abLen); @@ -90,17 +90,17 @@ global.JSSendArrayBufferViewTypes = () => { const ab1 = new ArrayBuffer(4321); const u8 = new Uint8Array(ab1, 2468, 1000); u8[0] = 1; - deno.send(u8); + libdeno.send(u8); // Send Uint32Array. const ab2 = new ArrayBuffer(4321); const u32 = new Uint32Array(ab2, 2468, 1000 / Uint32Array.BYTES_PER_ELEMENT); u32[0] = 0x02020202; - deno.send(u32); + libdeno.send(u32); // Send DataView. const ab3 = new ArrayBuffer(4321); const dv = new DataView(ab3, 2468, 1000); dv.setUint8(0, 3); - deno.send(dv); + libdeno.send(dv); }; global.JSSendNeutersBuffer = () => { @@ -109,7 +109,7 @@ global.JSSendNeutersBuffer = () => { assert(u8.byteLength === 1); assert(u8.buffer.byteLength === 1); assert(u8[0] === 42); - const r = deno.send(u8); + const r = libdeno.send(u8); assert(u8.byteLength === 0); assert(u8.buffer.byteLength === 0); assert(u8[0] === undefined); @@ -124,19 +124,19 @@ global.SnapshotBug = () => { global.ErrorHandling = () => { global.onerror = (message, source, line, col, error) => { - deno.print(`line ${line} col ${col}`); + libdeno.print(`line ${line} col ${col}`); assert("ReferenceError: notdefined is not defined" === message); assert(source === "helloworld.js"); assert(line === 3); assert(col === 1); assert(error instanceof Error); - deno.send(new Uint8Array([42])); + libdeno.send(new Uint8Array([42])); }; eval("\n\n notdefined()\n//# sourceURL=helloworld.js"); }; global.SendNullAllocPtr = () => { - deno.recv(msg => { + libdeno.recv(msg => { assert(msg instanceof Uint8Array); assert(msg.byteLength === 4); assert(msg[0] === "a".charCodeAt(0)); diff --git a/js/os.ts b/js/os.ts index 3344d1a51e..ab73395b3a 100644 --- a/js/os.ts +++ b/js/os.ts @@ -4,6 +4,7 @@ import { deno as fbs } from "gen/msg_generated"; import { assert } from "./util"; import * as util from "./util"; import { flatbuffers } from "flatbuffers"; +import { libdeno } from "./globals"; export function exit(exitCode = 0): never { const builder = new flatbuffers.Builder(); @@ -14,7 +15,7 @@ export function exit(exitCode = 0): never { fbs.Base.addMsg(builder, msg); fbs.Base.addMsgType(builder, fbs.Any.Exit); builder.finish(fbs.Base.endBase(builder)); - deno.send(builder.asUint8Array()); + libdeno.send(builder.asUint8Array()); throw Error("Unreachable"); } @@ -35,7 +36,7 @@ export function codeFetch( fbs.Base.addMsg(builder, msg); fbs.Base.addMsgType(builder, fbs.Any.CodeFetch); builder.finish(fbs.Base.endBase(builder)); - const resBuf = deno.send(builder.asUint8Array()); + const resBuf = libdeno.send(builder.asUint8Array()); // Process CodeFetchRes const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf)); const baseRes = fbs.Base.getRootAsBase(bb); @@ -73,7 +74,7 @@ export function codeCache( fbs.Base.addMsg(builder, msg); fbs.Base.addMsgType(builder, fbs.Any.CodeCache); builder.finish(fbs.Base.endBase(builder)); - const resBuf = deno.send(builder.asUint8Array()); + const resBuf = libdeno.send(builder.asUint8Array()); // Expect null or error. if (resBuf != null) { const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf)); diff --git a/js/runtime.ts b/js/runtime.ts index 2809ebdf8c..227d301c67 100644 --- a/js/runtime.ts +++ b/js/runtime.ts @@ -13,8 +13,9 @@ import { log } from "./util"; import { assetSourceCode } from "./assets"; import * as os from "./os"; import * as sourceMaps from "./v8_source_maps"; -import { window, globalEval } from "./globals"; -//import * as deno from "./deno"; +import { libdeno, window, globalEval } from "./globals"; +import * as deno from "./deno"; +import { RawSourceMap } from "./types"; const EOL = "\n"; const ASSETS = "/$asset$/"; @@ -40,26 +41,16 @@ window.onerror = ( os.exit(1); }; -// 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 | RawSourceMap => { util.log("getGeneratedContents", filename); if (filename === "gen/bundle/main.js") { - util.assert(window["mainSource"].length > 0); - return window["mainSource"]; + util.assert(libdeno.mainSource.length > 0); + return libdeno.mainSource; } else if (filename === "main.js.map") { - return mainSourceMap; + return libdeno.mainSourceMap; } else if (filename === "deno_main.js") { return ""; } else { diff --git a/js/types.d.ts b/js/types.d.ts index a9e013193c..85eda0cd06 100644 --- a/js/types.d.ts +++ b/js/types.d.ts @@ -116,6 +116,19 @@ export interface CallSite { isConstructor(): boolean; } +export interface StartOfSourceMap { + file?: string; + sourceRoot?: string; +} + +export interface RawSourceMap extends StartOfSourceMap { + version: string; + sources: string[]; + names: string[]; + sourcesContent?: string[]; + mappings: string; +} + declare global { // Declare "static" methods in Error interface ErrorConstructor { diff --git a/js/v8_source_maps.ts b/js/v8_source_maps.ts index 29091486c1..ec706cd44f 100644 --- a/js/v8_source_maps.ts +++ b/js/v8_source_maps.ts @@ -3,10 +3,9 @@ // Originated from source-map-support but has been heavily modified for deno. import { SourceMapConsumer, MappedPosition } from "source-map"; -import { RawSourceMap } from "source-map"; import * as base64 from "base64-js"; import { arrayToStr } from "./util"; -import { CallSite } from "./types"; +import { CallSite, RawSourceMap } from "./types"; const consumers = new Map(); diff --git a/src/binding.cc b/src/binding.cc index 19448ca2a0..7015660e3a 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -103,6 +103,7 @@ void HandleException(v8::Local context, d->last_exception = exception_str; } else { printf("Pre-Deno Exception %s\n", exception_str.c_str()); + exit(1); } } @@ -278,7 +279,7 @@ void InitializeContext(v8::Isolate* isolate, v8::Local context, auto global = context->Global(); auto deno_val = v8::Object::New(isolate); - CHECK(global->Set(context, deno::v8_str("deno"), deno_val).FromJust()); + CHECK(global->Set(context, deno::v8_str("libdeno"), deno_val).FromJust()); auto print_tmpl = v8::FunctionTemplate::New(isolate, Print); auto print_val = print_tmpl->GetFunction(context).ToLocalChecked(); @@ -295,17 +296,34 @@ void InitializeContext(v8::Isolate* isolate, v8::Local context, skip_onerror = true; { auto source = deno::v8_str(js_source.c_str()); - CHECK(global->Set(context, deno::v8_str("mainSource"), source).FromJust()); + CHECK( + deno_val->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); + v8::TryCatch try_catch(isolate); + v8::ScriptOrigin origin(v8_str("set_source_map.js")); + std::string source_map_parens = "(" + *source_map + ")"; + auto source_map_v8_str = deno::v8_str(source_map_parens.c_str()); + auto script = v8::Script::Compile(context, source_map_v8_str, &origin); + if (script.IsEmpty()) { + DCHECK(try_catch.HasCaught()); + HandleException(context, try_catch.Exception()); + return; + } + auto source_map_obj = script.ToLocalChecked()->Run(context); + if (source_map_obj.IsEmpty()) { + DCHECK(try_catch.HasCaught()); + HandleException(context, try_catch.Exception()); + return; + } + CHECK(deno_val + ->Set(context, deno::v8_str("mainSourceMap"), + source_map_obj.ToLocalChecked()) + .FromJust()); } } skip_onerror = false; diff --git a/src/deno_dir.rs b/src/deno_dir.rs index cabd9ed920..09f37933bc 100644 --- a/src/deno_dir.rs +++ b/src/deno_dir.rs @@ -189,7 +189,8 @@ impl DenoDir { base.join(module_specifier)? }; - let mut p = j.to_file_path() + let mut p = j + .to_file_path() .unwrap() .into_os_string() .into_string()