mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
Implement deno.readFile()
As an example of how to implement ops that have both sync and async versions.
This commit is contained in:
parent
c29392b25f
commit
35bc9ddf63
9 changed files with 100 additions and 79 deletions
2
BUILD.gn
2
BUILD.gn
|
@ -196,6 +196,7 @@ run_node("gen_declarations") {
|
|||
"js/global-eval.ts",
|
||||
"js/globals.ts",
|
||||
"js/os.ts",
|
||||
"js/read_file.ts",
|
||||
"js/text_encoding.ts",
|
||||
"js/timers.ts",
|
||||
"js/tsconfig.generated.json",
|
||||
|
@ -234,6 +235,7 @@ run_node("bundle") {
|
|||
"js/main.ts",
|
||||
"js/os.ts",
|
||||
"js/plugins.d.ts",
|
||||
"js/read_file.ts",
|
||||
"js/text_encoding.ts",
|
||||
"js/timers.ts",
|
||||
"js/types.ts",
|
||||
|
|
|
@ -7,12 +7,12 @@ export {
|
|||
FileInfo,
|
||||
makeTempDirSync,
|
||||
mkdirSync,
|
||||
readFileSync,
|
||||
renameSync,
|
||||
statSync,
|
||||
lstatSync,
|
||||
writeFileSync
|
||||
} from "./os";
|
||||
export { readFileSync, readFile } from "./read_file";
|
||||
export { ErrorKind, DenoError } from "./errors";
|
||||
export { libdeno } from "./libdeno";
|
||||
export const argv: string[] = [];
|
||||
|
|
38
js/os.ts
38
js/os.ts
|
@ -126,37 +126,6 @@ export function mkdirSync(path: string, mode = 0o777): void {
|
|||
sendSync(builder, fbs.Any.MkdirSync, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the file.
|
||||
* import { readFileSync } from "deno";
|
||||
*
|
||||
* const decoder = new TextDecoder("utf-8");
|
||||
* const data = readFileSync("hello.txt");
|
||||
* console.log(decoder.decode(data));
|
||||
*/
|
||||
export function readFileSync(filename: string): Uint8Array {
|
||||
/* Ideally we could write
|
||||
const res = sendSync({
|
||||
command: fbs.Command.READ_FILE_SYNC,
|
||||
readFileSyncFilename: filename
|
||||
});
|
||||
return res.readFileSyncData;
|
||||
*/
|
||||
const builder = new flatbuffers.Builder();
|
||||
const filename_ = builder.createString(filename);
|
||||
fbs.ReadFileSync.startReadFileSync(builder);
|
||||
fbs.ReadFileSync.addFilename(builder, filename_);
|
||||
const msg = fbs.ReadFileSync.endReadFileSync(builder);
|
||||
const baseRes = sendSync(builder, fbs.Any.ReadFileSync, msg);
|
||||
assert(baseRes != null);
|
||||
assert(fbs.Any.ReadFileSyncRes === baseRes!.msgType());
|
||||
const res = new fbs.ReadFileSyncRes();
|
||||
assert(baseRes!.msg(res) != null);
|
||||
const dataArray = res.dataArray();
|
||||
assert(dataArray != null);
|
||||
return new Uint8Array(dataArray!);
|
||||
}
|
||||
|
||||
function createEnv(_msg: fbs.EnvironRes): { [index: string]: string } {
|
||||
const env: { [index: string]: string } = {};
|
||||
|
||||
|
@ -365,13 +334,6 @@ export function writeFileSync(
|
|||
* renameSync(oldpath, newpath);
|
||||
*/
|
||||
export function renameSync(oldpath: string, newpath: string): void {
|
||||
/* Ideally we could write:
|
||||
const res = sendSync({
|
||||
command: fbs.Command.RENAME_SYNC,
|
||||
renameOldPath: oldpath,
|
||||
renameNewPath: newpath
|
||||
});
|
||||
*/
|
||||
const builder = new flatbuffers.Builder();
|
||||
const _oldpath = builder.createString(oldpath);
|
||||
const _newpath = builder.createString(newpath);
|
||||
|
|
|
@ -85,34 +85,6 @@ test(async function lstatSyncNotFound() {
|
|||
assertEqual(badInfo, undefined);
|
||||
});
|
||||
|
||||
test(async function readFileSyncSuccess() {
|
||||
const data = deno.readFileSync("package.json");
|
||||
if (!data.byteLength) {
|
||||
throw Error(
|
||||
`Expected positive value for data.byteLength ${data.byteLength}`
|
||||
);
|
||||
}
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const json = decoder.decode(data);
|
||||
const pkg = JSON.parse(json);
|
||||
assertEqual(pkg.name, "deno");
|
||||
});
|
||||
|
||||
/* TODO We should be able to catch specific types.
|
||||
test(function tests_readFileSync_NotFound() {
|
||||
let caughtError = false;
|
||||
let data;
|
||||
try {
|
||||
data = deno.readFileSync("bad_filename");
|
||||
} catch (e) {
|
||||
caughtError = true;
|
||||
assert(e instanceof deno.NotFound);
|
||||
}
|
||||
assert(caughtError);
|
||||
assert(data === undefined);
|
||||
});
|
||||
*/
|
||||
|
||||
testPerm({ write: true }, function writeFileSyncSuccess() {
|
||||
const enc = new TextEncoder();
|
||||
const data = enc.encode("Hello");
|
||||
|
|
50
js/read_file.ts
Normal file
50
js/read_file.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||
import * as fbs from "gen/msg_generated";
|
||||
import { flatbuffers } from "flatbuffers";
|
||||
import { assert } from "./util";
|
||||
import * as dispatch from "./dispatch";
|
||||
|
||||
/**
|
||||
* Read the entire contents of a file synchronously.
|
||||
*
|
||||
* import { readFileSync } from "deno";
|
||||
* const decoder = new TextDecoder("utf-8");
|
||||
* const data = readFileSync("hello.txt");
|
||||
* console.log(decoder.decode(data));
|
||||
*/
|
||||
export function readFileSync(filename: string): Uint8Array {
|
||||
return res(dispatch.sendSync(...req(filename)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the entire contents of a file.
|
||||
*
|
||||
* import { readFile } from "deno";
|
||||
* const decoder = new TextDecoder("utf-8");
|
||||
* const data = await readFile("hello.txt");
|
||||
* console.log(decoder.decode(data));
|
||||
*/
|
||||
export async function readFile(filename: string): Promise<Uint8Array> {
|
||||
return res(await dispatch.sendAsync(...req(filename)));
|
||||
}
|
||||
|
||||
function req(
|
||||
filename: string
|
||||
): [flatbuffers.Builder, fbs.Any, flatbuffers.Offset] {
|
||||
const builder = new flatbuffers.Builder();
|
||||
const filename_ = builder.createString(filename);
|
||||
fbs.ReadFile.startReadFile(builder);
|
||||
fbs.ReadFile.addFilename(builder, filename_);
|
||||
const msg = fbs.ReadFile.endReadFile(builder);
|
||||
return [builder, fbs.Any.ReadFile, msg];
|
||||
}
|
||||
|
||||
function res(baseRes: null | fbs.Base): Uint8Array {
|
||||
assert(baseRes != null);
|
||||
assert(fbs.Any.ReadFileRes === baseRes!.msgType());
|
||||
const msg = new fbs.ReadFileRes();
|
||||
assert(baseRes!.msg(msg) != null);
|
||||
const dataArray = msg.dataArray();
|
||||
assert(dataArray != null);
|
||||
return new Uint8Array(dataArray!);
|
||||
}
|
34
js/read_file_test.ts
Normal file
34
js/read_file_test.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||
import { test, assert, assertEqual } from "./test_util.ts";
|
||||
import * as deno from "deno";
|
||||
|
||||
test(function readFileSyncSuccess() {
|
||||
const data = deno.readFileSync("package.json");
|
||||
assert(data.byteLength > 0);
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const json = decoder.decode(data);
|
||||
const pkg = JSON.parse(json);
|
||||
assertEqual(pkg.name, "deno");
|
||||
});
|
||||
|
||||
test(function readFileSyncNotFound() {
|
||||
let caughtError = false;
|
||||
let data;
|
||||
try {
|
||||
data = deno.readFileSync("bad_filename");
|
||||
} catch (e) {
|
||||
caughtError = true;
|
||||
assertEqual(e.kind, deno.ErrorKind.NotFound);
|
||||
}
|
||||
assert(caughtError);
|
||||
assert(data === undefined);
|
||||
});
|
||||
|
||||
test(async function readFileSuccess() {
|
||||
const data = await deno.readFile("package.json");
|
||||
assert(data.byteLength > 0);
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const json = decoder.decode(data);
|
||||
const pkg = JSON.parse(json);
|
||||
assertEqual(pkg.name, "deno");
|
||||
});
|
|
@ -3,5 +3,6 @@
|
|||
// But it can also be run manually: ./out/debug/deno js/unit_tests.ts
|
||||
import "./compiler_test.ts";
|
||||
import "./console_test.ts";
|
||||
import "./os_test.ts";
|
||||
import "./fetch_test.ts";
|
||||
import "./os_test.ts";
|
||||
import "./read_file_test.ts";
|
||||
|
|
|
@ -50,7 +50,7 @@ pub extern "C" fn msg_from_js(d: *const DenoC, buf: deno_buf) {
|
|||
msg::Any::TimerClear => handle_timer_clear,
|
||||
msg::Any::MakeTempDir => handle_make_temp_dir,
|
||||
msg::Any::MkdirSync => handle_mkdir_sync,
|
||||
msg::Any::ReadFileSync => handle_read_file_sync,
|
||||
msg::Any::ReadFile => handle_read_file,
|
||||
msg::Any::RenameSync => handle_rename_sync,
|
||||
msg::Any::SetEnv => handle_set_env,
|
||||
msg::Any::StatSync => handle_stat_sync,
|
||||
|
@ -430,20 +430,20 @@ fn handle_mkdir_sync(d: *const DenoC, base: &msg::Base) -> Box<Op> {
|
|||
}
|
||||
|
||||
// Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184
|
||||
fn handle_read_file_sync(_d: *const DenoC, base: &msg::Base) -> Box<Op> {
|
||||
let msg = base.msg_as_read_file_sync().unwrap();
|
||||
fn handle_read_file(_d: *const DenoC, base: &msg::Base) -> Box<Op> {
|
||||
let msg = base.msg_as_read_file().unwrap();
|
||||
let cmd_id = base.cmd_id();
|
||||
let filename = String::from(msg.filename().unwrap());
|
||||
Box::new(futures::future::result(|| -> OpResult {
|
||||
debug!("handle_read_file_sync {}", filename);
|
||||
debug!("handle_read_file {}", filename);
|
||||
let vec = fs::read(Path::new(&filename))?;
|
||||
// Build the response message. memcpy data into msg.
|
||||
// TODO(ry) zero-copy.
|
||||
let builder = &mut FlatBufferBuilder::new();
|
||||
let data_off = builder.create_vector(vec.as_slice());
|
||||
let msg = msg::ReadFileSyncRes::create(
|
||||
let msg = msg::ReadFileRes::create(
|
||||
builder,
|
||||
&msg::ReadFileSyncResArgs {
|
||||
&msg::ReadFileResArgs {
|
||||
data: Some(data_off),
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -453,7 +453,7 @@ fn handle_read_file_sync(_d: *const DenoC, base: &msg::Base) -> Box<Op> {
|
|||
builder,
|
||||
msg::BaseArgs {
|
||||
msg: Some(msg.as_union_value()),
|
||||
msg_type: msg::Any::ReadFileSyncRes,
|
||||
msg_type: msg::Any::ReadFileRes,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
|
|
|
@ -15,8 +15,8 @@ union Any {
|
|||
MakeTempDir,
|
||||
MakeTempDirRes,
|
||||
MkdirSync,
|
||||
ReadFileSync,
|
||||
ReadFileSyncRes,
|
||||
ReadFile,
|
||||
ReadFileRes,
|
||||
RenameSync,
|
||||
StatSync,
|
||||
StatSyncRes,
|
||||
|
@ -173,11 +173,11 @@ table MkdirSync {
|
|||
// mode specified by https://godoc.org/os#FileMode
|
||||
}
|
||||
|
||||
table ReadFileSync {
|
||||
table ReadFile {
|
||||
filename: string;
|
||||
}
|
||||
|
||||
table ReadFileSyncRes {
|
||||
table ReadFileRes {
|
||||
data: [ubyte];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue