简体   繁体   English

自定义Gulp.js插件:TypeError“路径必须是一个字符串。 收到undefined“

[英]Custom Gulp.js plugin: TypeError “Path must be a string. Received undefined”

I've found several threads on StackOverflow about TypeError: Path must be a string , even though I've not been able to apply the suggested solutions to my very case. 我在StackOverflow上找到了几个关于TypeError: Path must be a string线程TypeError: Path must be a string ,即使我无法将建议的解决方案应用到我的情况。

I'm trying to build a Gulp plugin that connects to the (paid) javascriptobfuscator.com service and use their POST API to obfuscate my JS. 我正在尝试构建一个连接到(付费)javascriptobfuscator.com服务的Gulp插件,并使用他们的POST API来混淆我的JS。

The Gulp task looks like: Gulp任务看起来像:

var gulp = require('gulp'),
    jso = require('./jsobfuscator');

gulp.task('jso', function() {
    // .jsx contain extendscript language, which as far as 
    // the service is concerned, could be treated as .js
    return gulp.src('.src/app/jsx/photoshop.jsx')
               .pipe(jso())
               .pipe(gulp.dest('./dist'))
});

The jsobfuscator.js file contains the following code: jsobfuscator.js文件包含以下代码:

var through = require('through2'),
    http = require('http'),
    gutil = require('gulp-util'),
    Readable = require('stream').Readable

module.exports = function() {
  /**
   * @this {Transform}
   */

    var transform = function(file, encoding, callback) {

        var that = this;

        var proj = {};
        proj.APIKey = "/* MyAPIKey*/";
        proj.APIPwd = "/* MyAPIPwd*/";
        proj.Name = "DoubleUSM";
        proj.ReorderCode = true;
        proj.ReplaceNames = true;
        proj.EncodeStrings = true;
        proj.MoveStrings = true;
        proj.MoveMembers = true;
        proj.DeepObfuscate = true;
        proj.SelfCompression = true;
        // Unsure about these two...
        proj.CompressionRatio = "Auto";
        proj.OptimizationMode = "Auto";

        var appJS = new Object();
        appJS.FileName = "app.js";
        appJS.FileCode = file.contents.toString('utf8');
        // Will try to implement multiple files later on
        proj.Items = [appJS];

        var postData = JSON.stringify(proj);

        // Length is OK
        gutil.log ("Length: " + Buffer.byteLength(postData, 'utf-8'))

        var options = {
            host: 'service.javascriptobfuscator.com',
            path: '/HttpApi.ashx',
            method: 'POST',
            headers: { 
                'Content-Type': 'text/json',
                'Content-Length': Buffer.byteLength(postData, 'utf-8')
            }
        };

        callback = function(response) {
            response.setEncoding('utf8');

            var str = '';
            response.on('data', function(chunk) {
                str += chunk;
            });

            response.on('end', function() {
                // I get the correct response here!
                gutil.log(JSON.stringify(JSON.parse(str), null, '  '));

                var resObj = JSON.parse(str);
                // Converting the received string into a Buffer
                var fileStream = new Readable();
                // resObj.Items[0].FileCode is where the obfuscated code belongs
                fileStream.push(resObj.Items[0].FileCode);
                fileStream.push(null);
                that.push(fileStream);
                callback();
            });
        }

        var req = http.request(options, callback);
        req.write(postData);
        req.end();
    };

    return through.obj(transform);
};

When I run the gulp task I apparently get the proper response from the javascriptobfuscator code (as you can see below) yet there's something wrong in the part where I pass along the file to the destination because I'm getting: 当我运行gulp任务时,我显然从javascriptobfuscator代码得到了正确的响应(如下所示)但是我将文件传递到目的地的部分出了问题,因为我得到了:

(master)*  gulp jso
[15:13:30] Using gulpfile ~/Dropbox/Developer/PROJECTS/DOUBLE USM/gulpfile.js
[15:13:30] Starting 'jso'...
[15:13:31] Lenght: 21897
[15:13:32] {
  "Type": "Succeed",
  "Items": [
    {
      "FileName": "app.js",
      "FileCode": /* ... Long, horrible, properly obfuscated blob here... */
    }
  ],
  "ErrorCode": null,
  "Message": null,
  "FileName": null,
  "LineNumber": null,
  "ExceptionToString": null
}
path.js:7
    throw new TypeError('Path must be a string. Received ' + inspect(path));
    ^

TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.resolve (path.js:1146:7)
    at DestroyableTransform.saveFile [as _transform] (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/lib/dest/index.js:36:26)
    at DestroyableTransform.Transform._read (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_transform.js:184:10)
    at DestroyableTransform.Transform._write (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_transform.js:172:12)
    at doWrite (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:237:10)
    at writeOrBuffer (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:227:5)
    at DestroyableTransform.Writable.write (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_writable.js:194:11)
    at DestroyableTransform.ondata (/Users/davidebarranca/Dropbox/Developer/PROJECTS/DOUBLE USM/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:546:20)
    at emitOne (events.js:96:13)

Admittedly I'm not an expert of Gulp plugins – I'm trying to build a functionality for my own private use. 不可否认,我不是Gulp插件的专家 - 我正在尝试为自己的私人用途构建一个功能。 It looks like I'm quite close, but I've been stuck in this dead end for a while and I need help from more experienced ones. 看起来我很亲密,但我已经陷入了这个死胡同一段时间,我需要更有经验的人的帮助。

Thanks in advance 提前致谢


Half-working update 半工作更新

Modifying the response.on('end') callback as follows, I've been able to finally write the file: 修改response.on('end')回调如下,我已经能够最终写入文件:

response.on('end', function() {

    var resObj = JSON.parse(str);

    var fileStream = new Readable();
    fileStream.push(resObj.Items[0].FileCode);
    fileStream.push(null);

    // Manually creating a new Vinyl file
    var jsFile = new Vinyl({
        cwd: file.cwd,
        base: file.base,
        path: file.path,
        contents: fileStream
    });

    return that.push(jsFile);
    // callback();
});

I had to comment out the final callback() , though, otherwise I would have run into an error pointing to the response.setEncoding('utf8'); 我不得不注释掉最后的callback() ,否则我会遇到指向response.setEncoding('utf8');的错误response.setEncoding('utf8'); line, being response undefined. 行, response未定义。

The problem is now that it seems like the task , in some way, never terminates . 问题是现在似乎任务在某种程度上永远不会终止 The console says Starting 'jso'... , the file is written, the console returns, but there's no Finished 'jso' after nn ms , and worst of all, I'm completely unable to chain more gulp tasks afterwards , so if I: 控制台说Starting 'jso'... ,文件被写入,控制台返回,但是Finished 'jso' after nn ms没有Finished 'jso' after nn ms ,最糟糕的是,我完全无法在之后链接更多的gulp任务 ,所以如果一世:

gulp.task('jso1', function() {
    return gulp.src('.src/app/jsx/photoshop.jsx')
               .pipe(jso())
               .pipe(gulp.dest('./dist'))
});

gulp.task('jso2', ['jso1'], function() {
    return gulp.src('.src/app/app.js')
               .pipe(jso())
               .pipe(gulp.dest('./dist'))
});

// then in the Terminal:
$ gulp jso2

The only thing that I get is jso1 starting, apparently working, but never finishing; 我得到的唯一的东西是jso1开始,显然工作,但从未完成; jso2 never runs. jso2永远不会运行。


Many hours of head scratching made me get to the answer. 几个小时的头部刮伤让我得到答案。 Briefly, in my Gulp plugin: 简而言之,在我的Gulp插件中:

  1. I had to return a new Vinyl file in the the response.on('end') callback: the file's contents property needs to be the stream from the server response. 我必须在response.on('end')回调中返回一个新的Vinyl文件 :文件的contents属性需要是来自服务器响应的流。
  2. My half-working solution's main flaw is that I've given the same name ( callback ) to two very different functions . 我的半工作解决方案的主要缺陷是我给两个非常不同的函数赋予了相同的名称( callback One is the callback from the initial transform function; 一个是来自初始transform函数的callback ; the other one is the http.request callback. 另一个是http.request回调。 Commenting out the last callback() call, after return that.push(jsFile); return that.push(jsFile);之后return that.push(jsFile);最后一个callback()调用return that.push(jsFile); prevented the whole Gulp task from ending. 阻止整个Gulp任务结束。

The full working code is as follows: 完整的工作代码如下:

var through  = require('through2'),
    http     = require('http'),
    gutil    = require('gulp-util'),
    Readable = require('stream').Readable,
    Vinyl    = require('vinyl');

module.exports = function() {

    var transform = function(file, encoding, callback) {

        if (file.isNull()) { return callback(null, file) }

        var that = this;

        var proj = {};
        proj.APIKey = "/* MyAPIKey */";
        proj.APIPwd = "/* APIPwd */";
        proj.Name = "Project";
        proj.ReorderCode = true;
        proj.ReplaceNames = true;
        proj.EncodeStrings = true;
        proj.MoveStrings = true;
        proj.MoveMembers = true;
        proj.DeepObfuscate = true;
        proj.SelfCompression = true;
        proj.CompressionRatio = "Auto";
        proj.OptimizationMode = "Auto";

        var appJS = new Object();
        appJS.FileName = "app.js";
        appJS.FileCode = file.contents.toString('utf8');

        proj.Items = [appJS];

        var postData = JSON.stringify(proj);

        var options = {
            host: 'service.javascriptobfuscator.com',
            path: '/HttpApi.ashx',
            method: 'POST',
            headers: { 
                'Content-Type': 'text/json',
                'Content-Length': Buffer.byteLength(postData, 'utf-8')
            }
        };

        /* Renamed to avoid confusion with transform's callback */
        postCallback = function(response) {

            response.setEncoding('utf8');
            var str = '';
            response.on('data', function(chunk) {
                str += chunk;
            });

            response.on('end', function() {

                var resObj = JSON.parse(str);
                var fileStream = new Readable();
                fileStream.push(resObj.Items[0].FileCode);
                fileStream.push(null);

                /* Return a new Vinyl File */
                var jsFile = new Vinyl({
                    cwd: file.cwd,
                    base: file.base,
                    path: file.path,
                    contents: fileStream
                });

                that.push(jsFile);
                callback();
            });
        }

        var req = http.request(options, postCallback);
        req.write(postData);
        req.end();

    };

    return through.obj(transform);
};

Perhaps there might be better ways to return the Vinyl file without creating a new one. 也许有更好的方法可以在不创建新文件的情况下返回Vinyl文件。

Another improvement would be to group all the source files and make a single http call to javascriptobfuscator API (it is possible in fact to add multiple files to the proj.Items array), but I have no idea how to group files in the source, pass them all at once to the Gulp plugin, and then split them back later. 另一个改进是将所有源文件分组并对javascriptobfuscator API进行单个http调用(实际上可以将多个文件添加到proj.Items数组中),但我不知道如何在源代码中对文件进行分组,将它们全部传递给Gulp插件,然后将它们拆分回来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 gulp-usemin TypeError:路径必须是字符串。 收到未定义 - gulp-usemin TypeError: Path must be a string. Received undefined 运行gulp会导致“ path.js:7抛出新的TypeError('路径必须是字符串。已接收'+ inspect(path));” - Running gulp gives “path.js:7 throw new TypeError('Path must be a string. Received ' + inspect(path));” Jest TypeError:路径必须是字符串。 收到未定义 - Jest TypeError: Path must be a string. Received undefined Firebase 与 react: TypeError: Path must be a string。 收到未定义 - Firebase with react: TypeError: Path must be a string. Received undefined gulp Iconify任务引发错误TypeError:路径必须是字符串。 收到假 - gulp Iconify task throws error TypeError: Path must be a string. Received false Grunt“watch”警告:Path必须是一个字符串。 收到undefined - Grunt “watch” Warning: Path must be a string. Received undefined 错误:TypeError [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。 尝试 node utils/nftport/uploadFiles.js 时收到 undefined - error:TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined when trying node utils/nftport/uploadFiles.js Jest测试失败“TypeError:Path必须是一个字符串。 收到未定义的“ - Jest test failed “TypeError: Path must be a string. Recieved undefined” 图片上传错误:TypeError [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。 接收类型未定义 - Image Upload Error: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined TypeError [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。 收到未定义和代码:'ERR_INVALID_ARG_TYPE' - TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined and code: 'ERR_INVALID_ARG_TYPE'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM