如何在Swift的JavaScriptCore中导入模块? [英] How to import modules in Swift's JavaScriptCore?

查看:124
本文介绍了如何在Swift的JavaScriptCore中导入模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Swift的JavaScriptCore框架来利用现有的使用ES6模块的JavaScript库.具体来说,是斯蒂芬·C·菲利普斯(Stephen C Phillips)的 morse-pro .我已将文件添加到Xcode游乐场,然后使用此代码加载库并在JavaScript上下文中运行它:

I'm trying to use Swift's JavaScriptCore framework to take advantage of an existing JavaScript library that uses ES6 modules. Specifically, morse-pro by Stephen C Phillips. I've added the files to an Xcode playground, then used this code to load the library and run it in the JavaScript context:

import JavaScriptCore
var jsContext = JSContext()
// set up exception handler for javascript errors
jsContext?.exceptionHandler = { context, exception in
    if let exc = exception {
        print("JS Exception:", exc.toString())
    }
}
// read the javascript files in and evaluate
if let jsSourcePath = Bundle.main.path(forResource: "morse-pro-master/src/morse-pro-message", ofType: "js") {
    do {
        let jsSourceContents = try String(contentsOfFile: jsSourcePath)
        jsContext?.evaluateScript(jsSourceContents)
    } catch {
        print(error.localizedDescription)
    }
}

这种方法可用于简单的"Hello world"测试,但由于以下JavaScript错误,它在morse-pro库中令人窒息:

This approach works fine with simple "Hello world" sort of tests, but it chokes on the morse-pro library with this JavaScript error:

SyntaxError:意外的标记"*".期望导入呼叫 只是一个论点.

SyntaxError: Unexpected token '*'. import call expects exactly one argument.

错误似乎是由morse-pro-message.js中的这一行引起的:

The error appears to be caused by this line in morse-pro-message.js:

import * as Morse from './morse-pro';

我相信它试图将所有的morse-pro文件作为模块导入.

which I believe is trying to import all the morse-pro files as a module.

我对ES6模块不熟悉,但是该库在正常的JavaScript上下文中似乎可以为其他人工作.我在Swift中加载库的方式有问题吗?还是模块是JavaScriptCore不支持的功能? (文档只是说它支持"JavaScript",并且没有更具体的说明.)

I'm not familiar with ES6 modules, but the library appears to be working for others in normal JavaScript contexts. Is there something wrong with the way I'm loading the library in Swift? Or are modules a feature that JavaScriptCore doesn't support? (The documentation just says it supports "JavaScript" and doesn't get any more specific.)

对于将我指向使该库在JavaScriptCore VM中运行的任何建议,我将不胜感激.

I would appreciate any suggestions that point me in the direction of getting this library running in a JavaScriptCore VM.

推荐答案

在黑暗中摸索后,我找到了一种无需手动更改即可使Swift可用的库的方法.

After much bumbling around in the dark, I found a way to make the library available to Swift without having to manually alter it.

首先,按照@estus的建议,我使用NPM安装了该库,该库将其转换为ES5,但不能解决依赖关系.因此,仍然是一堆单独的文件,它们使用requireexport关键字相互调用,而浏览器和JavaScriptCore都无法理解.

First, as @estus suggested, I installed the library using NPM, which converts it to ES5 but does not resolve the dependencies. So it's still a bunch of separate files that call each other with require and export keywords that neither browsers nor JavaScriptCore understand.

然后,我使用 Browserify 将所有依赖项捆绑到一个文件中,以便JavaScriptCore可以理解. Browserify的正常操作会隐藏所有代码,因此我使用了"--standalone"标志来告诉它使标记的功能可用.如果直接导出ES5文件,它将创建一个通用对象,并将导出的函数放在.default下.我希望它们更易于访问,因此我创建了一个新文件以列出导出,然后在该文件上运行Browserify.因此,例如,一个名为"morse-export.js"的文件包含:

Then I used Browserify to bundle all the dependencies into a single file so that JavaScriptCore could understand it. The normal operation of Browserify hides all the code, so I used the "--standalone" flag to tell it to make marked functions available. If you export the ES5 file directly, it creates a generic object and puts your exported functions under .default. I want them slightly more accessible, so I created a new file to list the exports and then ran Browserify on that. So for example, a file called "morse-export.js" containing:

module.exports.MorseMessage = require('./lib/morse-pro-message.js').default;

然后我像这样在其上运行Browserify:

Then I run Browserify on it like this:

browserify ./morse-export.js --standalone Morse > ./morse-bundle.js

并使用Bundle.main.path(forResource)将morse-bundle.js文件包含在我的Swift代码中.现在我可以使用Morse.MorseMessage访问MorseMessage类,回到Swift:

And include the morse-bundle.js file in my Swift code using Bundle.main.path(forResource). Now I can access the MorseMessage class using Morse.MorseMessage, so back in Swift:

jsContext?.evaluateScript("var morseMessage = new Morse.MorseMessage()")
print(jsContext!.evaluateScript("morseMessage.translate('abc')"))

打印".- -... -.-".如您所愿.

prints ".- -... -.-." as you would expect.

这样做的缺点是您必须手动添加要导出到导出文件的任何类和函数.尽管如此,这似乎是最简单的方法.如果有更好的方法,我很想听听!

The downside of this is that you have to manually add whatever classes and functions you want exported to your export file. Still, this seems to be the simplest way to do it. If there's a better way, I would love to hear about it!

这篇关于如何在Swift的JavaScriptCore中导入模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆