Fix sending dates through the protocol

Fixes #253.
This commit is contained in:
Asher 2019-04-04 18:24:21 -05:00
parent 278c59b920
commit e73eb74208
No known key found for this signature in database
GPG Key ID: 7BB4BA9C783D2BBC
9 changed files with 267 additions and 22 deletions

View File

@ -317,17 +317,7 @@ export class FsModule {
}
class Stats implements fs.Stats {
public readonly atime: Date;
public readonly mtime: Date;
public readonly ctime: Date;
public readonly birthtime: Date;
public constructor(private readonly stats: IStats) {
this.atime = new Date(stats.atime);
this.mtime = new Date(stats.mtime);
this.ctime = new Date(stats.ctime);
this.birthtime = new Date(stats.birthtime);
}
public constructor(private readonly stats: IStats) {}
public get dev(): number { return this.stats.dev; }
public get ino(): number { return this.stats.ino; }
@ -339,6 +329,10 @@ class Stats implements fs.Stats {
public get size(): number { return this.stats.size; }
public get blksize(): number { return this.stats.blksize; }
public get blocks(): number { return this.stats.blocks; }
public get atime(): Date { return this.stats.atime; }
public get mtime(): Date { return this.stats.mtime; }
public get ctime(): Date { return this.stats.ctime; }
public get birthtime(): Date { return this.stats.birthtime; }
public get atimeMs(): number { return this.stats.atimeMs; }
public get mtimeMs(): number { return this.stats.mtimeMs; }
public get ctimeMs(): number { return this.stats.ctimeMs; }

View File

@ -65,6 +65,11 @@ export const argumentToProto = (
const arg = new Argument.ProxyValue();
arg.setId(storeProxy(currentValue));
message.setProxy(arg);
} else if (currentValue instanceof Date
|| (currentValue && typeof currentValue.getTime === "function")) {
const arg = new Argument.DateValue();
arg.setDate(currentValue.toString());
message.setDate(arg);
} else if (currentValue !== null && typeof currentValue === "object") {
const arg = new Argument.ObjectValue();
const map = arg.getDataMap();
@ -136,6 +141,8 @@ export const protoToArgument = (
}
return createProxy(currentMessage.getProxy()!.getId());
case Argument.MsgCase.DATE:
return new Date(currentMessage.getDate()!.getDate());
case Argument.MsgCase.OBJECT:
const obj: { [Key: string]: any } = {};
currentMessage.getObject()!.getDataMap().forEach((argument, key) => {

View File

@ -24,10 +24,10 @@ export interface Stats {
mtimeMs: number;
ctimeMs: number;
birthtimeMs: number;
atime: Date | string;
mtime: Date | string;
ctime: Date | string;
birthtime: Date | string;
atime: Date;
mtime: Date;
ctime: Date;
birthtime: Date;
_isFile: boolean;
_isDirectory: boolean;
_isBlockDevice: boolean;

View File

@ -317,6 +317,7 @@ export class Server {
logger.trace(() => [
"sending reject",
field("id", id) ,
field("message", error.message),
]);
const failedMessage = new Method.Fail();

View File

@ -40,6 +40,10 @@ message Argument {
message UndefinedValue {}
message DateValue {
string date = 1;
}
oneof msg {
ErrorValue error = 1;
BufferValue buffer = 2;
@ -52,6 +56,7 @@ message Argument {
double number = 9;
string string = 10;
bool boolean = 11;
DateValue date = 12;
}
}

View File

@ -59,6 +59,11 @@ export class Argument extends jspb.Message {
getBoolean(): boolean;
setBoolean(value: boolean): void;
hasDate(): boolean;
clearDate(): void;
getDate(): Argument.DateValue | undefined;
setDate(value?: Argument.DateValue): void;
getMsgCase(): Argument.MsgCase;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Argument.AsObject;
@ -83,6 +88,7 @@ export namespace Argument {
number: number,
string: string,
pb_boolean: boolean,
date?: Argument.DateValue.AsObject,
}
export class ErrorValue extends jspb.Message {
@ -248,6 +254,26 @@ export namespace Argument {
}
}
export class DateValue extends jspb.Message {
getDate(): string;
setDate(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): DateValue.AsObject;
static toObject(includeInstance: boolean, msg: DateValue): DateValue.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: DateValue, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): DateValue;
static deserializeBinaryFromReader(message: DateValue, reader: jspb.BinaryReader): DateValue;
}
export namespace DateValue {
export type AsObject = {
date: string,
}
}
export enum MsgCase {
MSG_NOT_SET = 0,
ERROR = 1,
@ -261,6 +287,7 @@ export namespace Argument {
NUMBER = 9,
STRING = 10,
BOOLEAN = 11,
DATE = 12,
}
}

View File

@ -14,6 +14,7 @@ var global = Function('return this')();
goog.exportSymbol('proto.Argument', null, global);
goog.exportSymbol('proto.Argument.ArrayValue', null, global);
goog.exportSymbol('proto.Argument.BufferValue', null, global);
goog.exportSymbol('proto.Argument.DateValue', null, global);
goog.exportSymbol('proto.Argument.ErrorValue', null, global);
goog.exportSymbol('proto.Argument.FunctionValue', null, global);
goog.exportSymbol('proto.Argument.NullValue', null, global);
@ -223,6 +224,27 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.Argument.UndefinedValue.displayName = 'proto.Argument.UndefinedValue';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.Argument.DateValue = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.Argument.DateValue, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.Argument.DateValue.displayName = 'proto.Argument.DateValue';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
@ -505,7 +527,7 @@ if (goog.DEBUG && !COMPILED) {
* @private {!Array<!Array<number>>}
* @const
*/
proto.Argument.oneofGroups_ = [[1,2,3,4,5,6,7,8,9,10,11]];
proto.Argument.oneofGroups_ = [[1,2,3,4,5,6,7,8,9,10,11,12]];
/**
* @enum {number}
@ -522,7 +544,8 @@ proto.Argument.MsgCase = {
UNDEFINED: 8,
NUMBER: 9,
STRING: 10,
BOOLEAN: 11
BOOLEAN: 11,
DATE: 12
};
/**
@ -571,7 +594,8 @@ proto.Argument.toObject = function(includeInstance, msg) {
undefined: (f = msg.getUndefined()) && proto.Argument.UndefinedValue.toObject(includeInstance, f),
number: +jspb.Message.getFieldWithDefault(msg, 9, 0.0),
string: jspb.Message.getFieldWithDefault(msg, 10, ""),
pb_boolean: jspb.Message.getFieldWithDefault(msg, 11, false)
pb_boolean: jspb.Message.getFieldWithDefault(msg, 11, false),
date: (f = msg.getDate()) && proto.Argument.DateValue.toObject(includeInstance, f)
};
if (includeInstance) {
@ -660,6 +684,11 @@ proto.Argument.deserializeBinaryFromReader = function(msg, reader) {
var value = /** @type {boolean} */ (reader.readBool());
msg.setBoolean(value);
break;
case 12:
var value = new proto.Argument.DateValue;
reader.readMessage(value,proto.Argument.DateValue.deserializeBinaryFromReader);
msg.setDate(value);
break;
default:
reader.skipField();
break;
@ -774,6 +803,14 @@ proto.Argument.serializeBinaryToWriter = function(message, writer) {
f
);
}
f = message.getDate();
if (f != null) {
writer.writeMessage(
12,
f,
proto.Argument.DateValue.serializeBinaryToWriter
);
}
};
@ -1837,6 +1874,131 @@ proto.Argument.UndefinedValue.serializeBinaryToWriter = function(message, writer
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.Argument.DateValue.prototype.toObject = function(opt_includeInstance) {
return proto.Argument.DateValue.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.Argument.DateValue} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Argument.DateValue.toObject = function(includeInstance, msg) {
var obj = {
date: jspb.Message.getFieldWithDefault(msg, 1, "")
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.Argument.DateValue}
*/
proto.Argument.DateValue.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.Argument.DateValue;
return proto.Argument.DateValue.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.Argument.DateValue} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.Argument.DateValue}
*/
proto.Argument.DateValue.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setDate(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.Argument.DateValue.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.Argument.DateValue.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.Argument.DateValue} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.Argument.DateValue.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getDate();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* optional string date = 1;
* @return {string}
*/
proto.Argument.DateValue.prototype.getDate = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/** @param {string} value */
proto.Argument.DateValue.prototype.setDate = function(value) {
jspb.Message.setProto3StringField(this, 1, value);
};
/**
* optional ErrorValue error = 1;
* @return {?proto.Argument.ErrorValue}
@ -2199,6 +2361,39 @@ proto.Argument.prototype.hasBoolean = function() {
};
/**
* optional DateValue date = 12;
* @return {?proto.Argument.DateValue}
*/
proto.Argument.prototype.getDate = function() {
return /** @type{?proto.Argument.DateValue} */ (
jspb.Message.getWrapperField(this, proto.Argument.DateValue, 12));
};
/** @param {?proto.Argument.DateValue|undefined} value */
proto.Argument.prototype.setDate = function(value) {
jspb.Message.setOneofWrapperField(this, 12, proto.Argument.oneofGroups_[0], value);
};
/**
* Clears the message field making it undefined.
*/
proto.Argument.prototype.clearDate = function() {
this.setDate(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.Argument.prototype.hasDate = function() {
return jspb.Message.getField(this, 12) != null;
};
/**
* Oneof group definitions for this message. Each group defines the field

View File

@ -53,6 +53,11 @@ describe("child_process", () => {
await expect(getStdout(proc)).resolves.toContain("hi=donkey\n");
});
it("should eval", async () => {
const proc = cp.spawn("node", ["-e", "console.log('foo')"]);
await expect(getStdout(proc)).resolves.toContain("foo");
});
});
describe("fork", () => {

View File

@ -4,6 +4,8 @@ import * as util from "util";
import { Module } from "../src/common/proxy";
import { createClient, Helper } from "./helpers";
// tslint:disable deprecation to use fs.exists
describe("fs", () => {
const client = createClient();
// tslint:disable-next-line no-any
@ -242,6 +244,14 @@ describe("fs", () => {
await util.promisify(nativeFs.close)(fd);
});
it("should futimes existing file with date", async () => {
const file = await helper.createTmpFile();
const fd = await util.promisify(nativeFs.open)(file, "w");
await expect(util.promisify(fs.futimes)(fd, new Date(), new Date()))
.resolves.toBeUndefined();
await util.promisify(nativeFs.close)(fd);
});
it("should fail to futimes nonexistent file", async () => {
await expect(util.promisify(fs.futimes)(99999, 9999, 9999))
.rejects.toThrow("EBADF");
@ -346,7 +356,7 @@ describe("fs", () => {
it("should read existing file", async () => {
const fd = await util.promisify(nativeFs.open)(__filename, "r");
const stat = await util.promisify(nativeFs.fstat)(fd);
const buffer = new Buffer(stat.size);
const buffer = Buffer.alloc(stat.size);
let bytesRead = 0;
let chunkSize = 2048;
while (bytesRead < stat.size) {
@ -364,7 +374,7 @@ describe("fs", () => {
});
it("should fail to read nonexistent file", async () => {
await expect(util.promisify(fs.read)(99999, new Buffer(10), 9999, 999, 999))
await expect(util.promisify(fs.read)(99999, Buffer.alloc(10), 9999, 999, 999))
.rejects.toThrow("EBADF");
});
});
@ -466,6 +476,7 @@ describe("fs", () => {
expect(stat).toMatchObject({
size: nativeStat.size,
});
expect(typeof stat.mtime.getTime()).toBe("number");
expect(stat.isFile()).toBe(true);
});
@ -493,7 +504,7 @@ describe("fs", () => {
const destination = helper.tmpFile();
await expect(util.promisify(fs.symlink)(source, destination))
.resolves.toBeUndefined();
expect(util.promisify(nativeFs.exists)(source))
await expect(util.promisify(nativeFs.exists)(source))
.resolves.toBe(true);
});
@ -525,7 +536,7 @@ describe("fs", () => {
const file = await helper.createTmpFile();
await expect(util.promisify(fs.unlink)(file))
.resolves.toBeUndefined();
expect(util.promisify(nativeFs.exists)(file))
await expect(util.promisify(nativeFs.exists)(file))
.resolves.toBe(false);
});