在 JavaScriptCore 中获取默认导出 快速版本改进?

问题描述

目标:我正在尝试在 JavaScriptCore 中运行 JSLint。

旧版本

较早的 JSLint 版本公开了一个名为 JSLINT 的全局函数,如下所示:

var JSLINT = (function () {
    ...
}

这很容易在 JavaScriptCore 中检索和执行:

// Assume 'ctx' is a JSGlobalContextRef
// Assume we have already called JSEvaluateScript()

JsstringRef jsFunctionName = JsstringCreateWithUTF8CString("JSLINT");
JSValueRef jsLintFunctionValue = JSObjectGetProperty(ctx,jscontextGetGlobalObject(ctx),jsFunctionName,NULL);
Jsstringrelease(jsFunctionName);
    
JSObjectRef jsLintFunction = JSValuetoObject(ctx,jsLintFunctionValue,&exception);

有了这个引用,我就可以使用 JSObjectCallAsFunction() 来执行函数。完美运行。

新版本

现在,JSLint 已经转向了这个:

export default Object.freeze(function jslint(
    source = "",option_object = empty(),global_array = []
) { 
    ... 
});

JavaScriptCore 的文档很差。我尝试了很多东西,但显然缺少一些明显的东西。我现在如何检索和执行 jslint 函数

解决方法

快速版本

如果@kaizhu 的回答没有给你想要的,另一个接近你以前的状态的选择是......

  1. 注释掉两行导出代码 that starts on this line
  2. 参考小写 jslint

这里有两行你需要用今天的 JSLint 版本注释掉。

// export default Object.freeze(jslint_export);
// jslint_import_meta_url = import.meta.url;

如果您在项目中包含现在已编辑的文件,则函数 jslint 在您的全局范围内。

console.log(JSON.stringify(jslint("var a = 5").warnings,null,"  "))

结果:

[
  {
    "a": ";","b": "(end)","code": "expected_a_b","column": 9,"line": 1,"line_source": "var a = 5","name": "JSLintError","message": "Expected ';' and instead saw '(end)'.","formatted_message": " 1. \u001b[31mExpected ';' and instead saw '(end)'.\u001b[39m \u001b[90m// line 1,column 9\u001b[39m\n    var a = 5"
  }
]

我认为您对代码所做的唯一更改是将 jslint 小写:

JSStringRef jsFunctionName = JSStringCreateWithUTF8CString("jslint");

改进?

请注意,使用 jslint_export 可能“更合适”,它是 jslint 的冻结副本。

JSStringRef jsFunctionName = JSStringCreateWithUTF8CString("jslint_export");

如果您真的愿意,您可以将 jslint_export 变量替换为 JSLINT,而根本不更改您的 JavaScriptCore 代码。

// let jslint_export;              // The jslint object to be exported.
let JSLINT;                        // The jslint object to be exported.

// lots of stuff skipped

// jslint_export = Object.freeze(Object.assign(jslint,{
JSLINT = Object.freeze(Object.assign(jslint,{
    cli: Object.freeze(jslint_cli),edition: jslint_edition,jslint: Object.freeze(jslint.bind(undefined))
}));

我必须再次检查旧代码以查看其行为是否相同,但请注意实际的 linting 函数将在该构造中的 JSLINT.jslint 上。

我不知道为什么在当前版本的 JSLint 中有如此多的全局范围污染。为什么这并不都存在于 IIFE 中令人困惑;我觉得以前是?无论如何,这应该可以解决您的问题。

,

将 jslint 作为 es-module 导入的说明是 here

/*jslint devel*/
import jslint from "./jslint.mjs";
let code = "console.log('hello world');\n";
let result = jslint(code);
result.warnings.forEach(function ({
    formatted_message
}) {
    console.error(formatted_message);
});

// stderr
// 1 Undeclared 'console'. // line 1,column 1
// console.log('hello world');
// 2 Use double quotes,not single quotes. // line 1,column 13
// console.log('hello world');