Skip to content

Commit

Permalink
Implement writeFileSync
Browse files Browse the repository at this point in the history
In collaboration with Tommy Savaria <tommy.savaria@protonmail.ch>
  • Loading branch information
ry committed Aug 22, 2018
1 parent e7cab71 commit 7d7263c
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 6 deletions.
2 changes: 1 addition & 1 deletion js/deno.ts
@@ -1,4 +1,4 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
// Public deno module.
export { exit, readFileSync } from "./os";
export { exit, readFileSync, writeFileSync } from "./os";
export { libdeno } from "./globals";
25 changes: 21 additions & 4 deletions js/os.ts
Expand Up @@ -121,15 +121,32 @@ export function readFileSync(filename: string): Uint8Array {
export function writeFileSync(
filename: string,
data: Uint8Array,
perm: number
perm = 0o666
): void {
util.notImplemented();
/*
pubInternal("os", {
/* Ideally we could write:
const res = send({
command: fbs.Command.WRITE_FILE_SYNC,
writeFileSyncFilename: filename,
writeFileSyncData: data,
writeFileSyncPerm: perm
});
*/
const builder = new flatbuffers.Builder();
const filename_ = builder.createString(filename);
const dataOffset = fbs.WriteFileSync.createDataVector(builder, data);
fbs.WriteFileSync.startWriteFileSync(builder);
fbs.WriteFileSync.addFilename(builder, filename_);
fbs.WriteFileSync.addData(builder, dataOffset);
fbs.WriteFileSync.addPerm(builder, perm);
const msg = fbs.WriteFileSync.endWriteFileSync(builder);
fbs.Base.startBase(builder);
fbs.Base.addMsg(builder, msg);
fbs.Base.addMsgType(builder, fbs.Any.WriteFileSync);
builder.finish(fbs.Base.endBase(builder));
const resBuf = libdeno.send(builder.asUint8Array());
if (resBuf != null) {
const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf!));
const baseRes = fbs.Base.getRootAsBase(bb);
maybeThrowError(baseRes);
}
}
30 changes: 30 additions & 0 deletions js/unit_tests.ts
Expand Up @@ -5,6 +5,7 @@

import { test, assert, assertEqual } from "./testing/testing.ts";
import { readFileSync } from "deno";
import * as deno from "deno";

import "./compiler_test.ts";

Expand Down Expand Up @@ -109,6 +110,35 @@ test(function tests_readFileSync_NotFound() {
});
*/

/* TODO(ry) Add this once we can create a tmpDir to write the file into.
test(function writeFileSyncSuccess() {
const enc = new TextEncoder();
const dataWritten = enc.encode("Hello");
const filename = "TEMPDIR/test.txt";
deno.writeFileSync(filename, dataWritten, 0o666);
const dataRead = readFileSync(filename);
assertEqual(dataRead, dataWritten);
});
*/

// For this test to pass we need --allow-write permission.
// Otherwise it will fail with deno.PermissionDenied instead of deno.NotFound.
test(function writeFileSyncFail() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = "/baddir/test.txt";
// The following should fail because /baddir doesn't exist (hopefully).
let caughtError = false;
try {
deno.writeFileSync(filename, data);
} catch (e) {
caughtError = true;
// TODO assertEqual(e, deno.NotFound);
assertEqual(e.name, "deno.NotFound");
}
assert(caughtError);
});

test(async function tests_fetch() {
const response = await fetch("http://localhost:4545/package.json");
const json = await response.json();
Expand Down
6 changes: 6 additions & 0 deletions src/fs.rs
@@ -1,6 +1,7 @@
use std;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::path::Path;

pub fn read_file_sync(path: &Path) -> std::io::Result<Vec<u8>> {
Expand All @@ -17,6 +18,11 @@ pub fn read_file_sync_string(path: &Path) -> std::io::Result<String> {
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))
}

pub fn write_file_sync(path: &Path, content: &[u8]) -> std::io::Result<()> {
let mut f = File::create(path)?;
f.write_all(content)
}

pub fn mkdir(path: &Path) -> std::io::Result<()> {
debug!("mkdir -p {}", path.display());
assert!(path.has_root(), "non-has_root not yet implemented");
Expand Down
30 changes: 30 additions & 0 deletions src/handlers.rs
Expand Up @@ -70,6 +70,14 @@ pub extern "C" fn msg_from_js(d: *const DenoC, buf: deno_buf) {
let filename = msg.filename().unwrap();
handle_read_file_sync(d, &mut builder, filename)
}
msg::Any::WriteFileSync => {
// TODO base.msg_as_WriteFileSync();
let msg = msg::WriteFileSync::init_from_table(base.msg().unwrap());
let filename = msg.filename().unwrap();
let data = msg.data().unwrap();
let perm = msg.perm();
handle_write_file_sync(d, &mut builder, filename, data, perm)
}
_ => panic!(format!(
"Unhandled message {}",
msg::enum_name_any(msg_type)
Expand Down Expand Up @@ -413,6 +421,28 @@ fn handle_read_file_sync(
))
}

fn handle_write_file_sync(
d: *const DenoC,
builder: &mut FlatBufferBuilder,
filename: &str,
data: &[u8],
perm: u32,
) -> HandlerResult {
debug!("handle_write_file_sync {}", filename);
let deno = from_c(d);
if deno.flags.allow_write {
// TODO(ry) Use perm.
fs::write_file_sync(Path::new(filename), data)?;
Ok(null_buf())
} else {
let err = std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"allow_write is off.",
);
Err(err.into())
}
}

// TODO(ry) Use Deno instead of DenoC as first arg.
fn remove_timer(d: *const DenoC, timer_id: u32) {
let deno = from_c(d);
Expand Down
2 changes: 1 addition & 1 deletion tools/test.py
Expand Up @@ -41,7 +41,7 @@ def main(argv):

deno_exe = os.path.join(build_dir, "deno" + executable_suffix)
check_exists(deno_exe)
run([deno_exe, "js/unit_tests.ts"])
run([deno_exe, "js/unit_tests.ts", "--allow-write"])

check_exists(deno_exe)
check_output_test(deno_exe)
Expand Down

0 comments on commit 7d7263c

Please sign in to comment.