From 34a1da33458a97d2efc1a3d74a31b05602ddce81 Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Mon, 13 Dec 2021 05:46:42 -0800 Subject: [PATCH] Implement fs.stat and fs.readlink Summary: Fixes issue for the stackTraceMapper Reviewed By: aigoncharov Differential Revision: D32987161 fbshipit-source-id: 660f49a1bdf61b2fd2963874ef23dfd284f71128 --- desktop/flipper-common/src/server-types.tsx | 17 +++++++++++++++ .../flipper-plugin/src/plugin/FlipperLib.tsx | 5 ++++- .../src/test-utils/test-utils.tsx | 2 ++ .../src/FlipperServerImpl.tsx | 21 ++++++++++++++++++- .../utils/flipperLibImplementation/index.tsx | 4 ++++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/desktop/flipper-common/src/server-types.tsx b/desktop/flipper-common/src/server-types.tsx index 032105232..d15384066 100644 --- a/desktop/flipper-common/src/server-types.tsx +++ b/desktop/flipper-common/src/server-types.tsx @@ -132,6 +132,21 @@ export type IOSDeviceParams = { state?: string; }; +// Serializable subset of StatsBase from fs.d.ts +export interface FSStatsLike { + isFile: boolean; + isDirectory: boolean; + isSymbolicLink: boolean; + mode: number; + uid: number; + gid: number; + size: number; + atimeMs: number; + mtimeMs: number; + ctimeMs: number; + birthtimeMs: number; +} + export type FlipperServerCommands = { 'node-api-fs-access': (path: string, mode?: number) => Promise; 'node-api-fs-pathExists': (path: string, mode?: number) => Promise; @@ -146,6 +161,8 @@ export type FlipperServerCommands = { dest: string, flags?: number, ) => Promise; + 'node-api-fs-stat': (path: string) => Promise; + 'node-api-fs-readlink': (path: string) => Promise; /** * @throws ExecError */ diff --git a/desktop/flipper-plugin/src/plugin/FlipperLib.tsx b/desktop/flipper-plugin/src/plugin/FlipperLib.tsx index c9672f8e8..57eefc4e0 100644 --- a/desktop/flipper-plugin/src/plugin/FlipperLib.tsx +++ b/desktop/flipper-plugin/src/plugin/FlipperLib.tsx @@ -24,6 +24,7 @@ import { RmOptions, fsConstants, EnvironmentInfo, + FSStatsLike, } from 'flipper-common'; export type FileEncoding = 'utf-8' | 'base64'; @@ -49,6 +50,7 @@ export type RemoteServerContext = { ): Promise>; }; fs: { + constants: typeof fsConstants; access(path: string, mode?: number): Promise; pathExists(path: string, mode?: number): Promise; unlink(path: string): Promise; @@ -62,7 +64,8 @@ export type RemoteServerContext = { ): Promise; rm(path: string, options?: RmOptions): Promise; copyFile(src: string, dest: string, flags?: number): Promise; - constants: typeof fsConstants; + stat(path: string): Promise; + readlink(path: string): Promise; }; downloadFile( url: string, diff --git a/desktop/flipper-plugin/src/test-utils/test-utils.tsx b/desktop/flipper-plugin/src/test-utils/test-utils.tsx index d28477267..5f33d7225 100644 --- a/desktop/flipper-plugin/src/test-utils/test-utils.tsx +++ b/desktop/flipper-plugin/src/test-utils/test-utils.tsx @@ -413,6 +413,8 @@ export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib { rm: jest.fn(), copyFile: jest.fn(), constants: fsConstants, + stat: jest.fn(), + readlink: jest.fn(), }, downloadFile: jest.fn(), }, diff --git a/desktop/flipper-server-core/src/FlipperServerImpl.tsx b/desktop/flipper-server-core/src/FlipperServerImpl.tsx index a5673e9e5..b5cb2a7be 100644 --- a/desktop/flipper-server-core/src/FlipperServerImpl.tsx +++ b/desktop/flipper-server-core/src/FlipperServerImpl.tsx @@ -49,7 +49,7 @@ import {promises} from 'fs'; // Electron 11 runs on Node 12 which does not support fs.promises.rm import rm from 'rimraf'; -const {access, copyFile, mkdir, unlink} = promises; +const {access, copyFile, mkdir, unlink, stat, readlink} = promises; export const SERVICE_FLIPPER = 'flipper.oAuthToken'; @@ -239,6 +239,25 @@ export class FlipperServerImpl implements FlipperServer { ), ), 'node-api-fs-copyFile': copyFile, + 'node-api-fs-stat': async (path) => { + const stats = await stat(path); + const {atimeMs, birthtimeMs, ctimeMs, gid, mode, mtimeMs, size, uid} = + stats; + return { + atimeMs, + birthtimeMs, + ctimeMs, + gid, + mode, + mtimeMs, + size, + uid, + isDirectory: stats.isDirectory(), + isFile: stats.isFile(), + isSymbolicLink: stats.isSymbolicLink(), + }; + }, + 'node-api-fs-readlink': readlink, // TODO: Do we need API to cancel an active download? 'download-file-start': commandDownloadFileStartFactory( this.emit.bind(this), diff --git a/desktop/flipper-ui-core/src/utils/flipperLibImplementation/index.tsx b/desktop/flipper-ui-core/src/utils/flipperLibImplementation/index.tsx index afa243963..ad529ca0d 100644 --- a/desktop/flipper-ui-core/src/utils/flipperLibImplementation/index.tsx +++ b/desktop/flipper-ui-core/src/utils/flipperLibImplementation/index.tsx @@ -111,6 +111,10 @@ export function initializeFlipperLibImplementation( flags, ), constants: fsConstants, + stat: async (path: string) => + renderHost.flipperServer.exec('node-api-fs-stat', path), + readlink: async (path: string) => + renderHost.flipperServer.exec('node-api-fs-readlink', path), }, downloadFile: downloadFileFactory(renderHost), },