天道酬勤,学无止境

how to circumvent Kotlin's restriction "Type parameter is forbidden for catch parameter"

I have defined the following function:

inline fun <T> T.tryTo(block: T.() -> Unit): T? {
    try {
        block()
    } catch (ex: IllegalArgumentException) {
        return this
    }
    return null
}

The purpose is to build a chain of try-actions on an object, e.g.:

val input: String = getInput();

input.tryTo /* treat as a file name and open the file */ {
    Desktop.getDesktop().open(File(this))
}?.tryTo /* treat as a number */ {
    try {
        doSomethingWithTheNumber(parseInt(this))
    } catch (ex: NumberFormatException) {
        throw IllegalArgumentException()
    }
}?.tryTo {
    println("All options tried, none worked out. Don't know how to treat this input.")
}

So far that works fine.

But, as you can see in the middle tryTo-block ("treat as a number"), it is inconvenient to rethrow an "expected" exception as an IllegalArgumentException to keep the schema working. It would be nicer to write:

val input: String = getInput();

input.tryTo<IllegalArgumentException> /* treat as a file name and open the file */ {
    Desktop.getDesktop().open(File(this))
}?.tryTo<NumberFormatException> /* treat as a number */ {
    doSomethingWithTheNumber(parseInt(this))
}?.tryTo<Exception> {
    println("All options tried, none worked out. Don't know how to treat this input.")
}

So, I have rewritten the function tryTo to:

inline fun <T, X: Exception> T.tryTo(block: T.() -> Unit): T? {
    try {
        block()
    } catch (ex: X) {
        return this
    }
    return null
}

Unfortunately, the latter does not compile: "Type parameter is forbidden for catch parameter".

How to circumvent this restriction?


Addendum:

Now I've got it to:

inline fun <T, reified X: Exception> T.tryTo(block: T.() -> Unit): T? {
    try {
        block()
    } catch (ex: Exception) {
        return if (ex is X) this else throw ex
    }
    return null
}

But I'm still not happy with this because it requires me to specify both types explicitly ("Type inference failed..." / "2 type arguments expected ..."):

input.tryTo<String, IllegalArgumentException> /* treat as a file in the stapel-directory */ {
    ...
}

though the first type parameter is obvious as inferable from the receiver object.

评论

I thought this would be possible if you just made the type parameter reified, but apparently it is not. I did find the source of this check, and it quite clearly errors for any sort of type parameter in a catch clause, whether it's reified or not.

The commit message that added these checks references this issue - apparently the catch clause with a type parameter was catching all thrown Exception instances, and crashing with a ClassCastException if the exception wasn't of the specified type.

A possible workaround for your case comes from this answer for the similar Java question - if the generic type is reified, you can check if the exception thrown was of that specific type, which I believe makes this function what you're looking for:

inline fun <T, reified X : Exception> T.tryTo(block: T.() -> Unit): T? {
    try {
        block()
    } catch (ex: Exception) {
        if (ex is X) {
            return this
        }
    }
    return null
}

Although the call site gets quite ugly because you can't just specify the second type parameter of a function call if it has two type parameters:

val input: String = getInput()

input.tryTo<String, IllegalArgumentException> /* treat as a file name and open the file */ {
    Desktop.getDesktop().open(File(this))
}?.tryTo<String, NumberFormatException> /* treat as a number */ {
    doSomethingWithTheNumber(parseInt(this))
}?.tryTo<String, Exception> {
    println("All options tried, none worked out. Don't know how to treat this input.")
}

A slightly nicer alternative to the above, and closer to the original Java answer:

inline fun <T> T.tryTo(exceptionType: KClass<out Exception>, block: T.() -> Unit): T? {
    try {
        block()
    } catch (ex: Exception) {
        if (exceptionType.isInstance(ex)) {
            return this
        }
    }
    return null
}

With the KClass instances passed in like so:

input.tryTo(IllegalArgumentException::class) /* treat as a file name and open the file */ {
    Desktop.getDesktop().open(File(this))
}?.tryTo(NumberFormatException::class) /* treat as a number */ {
    doSomethingWithTheNumber(parseInt(this))
}?.tryTo(Exception::class) {
    println("All options tried, none worked out. Don't know how to treat this input.")
}

you can simply remove the receiver parameter

and it is better to use ?: then ?. for else semantic

inline fun <reified E : Throwable> runIgnoring(block: () -> Unit): Unit? {
    return try {
        block()
    } catch (e: Throwable) {
        if (e is E) null else throw e
    }
}

val input: String = getInput()

runIgnoring<IllegalArgumentException> /* treat as a file name and open the file */ {
    Desktop.getDesktop().open(File(input))
} ?: runIgnoring<NumberFormatException> /* treat as a number */ {
    doSomethingWithTheNumber(parseInt(input))
} ?: run {
    println("All options tried, none worked out. Don't know how to treat this input.")
}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • How to circumvent GHC Stage Restriction?
    I am writing a code generator whose output depends on datatype fields description which is stored in their class instances. However, I cannot find how to run a function with a TH-generated argument. {-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-} module Generator where import Language.Haskell.TH import Language.Haskell.TH.Syntax data Description = Description String [Description] deriving Show class HasDescription a where getDescription :: a -> Description instance HasDescription Int where getDescription _ = Description "Int" [] instance (HasDescription a, HasDescription b) =>
  • When is it necessary to circumvent Rust's borrow checker?
    I'm implementing Conway's game of life to teach myself Rust. The idea is to implement a single-threaded version first, optimize it as much as possible, then do the same for a multi-threaded version. I wanted to implement an alternative data layout which I thought might be more cache-friendly. The idea is to store the status of two cells for each point on a board next to each other in memory in a vector, one cell for reading the current generation's status from and one for writing the next generation's status to, alternating the access pattern for each generation's computation (which can be
  • 什么时候需要绕过 Rust 的借用检查器?(When is it necessary to circumvent Rust's borrow checker?)
    问题 我正在实施康威的生活游戏来自学 Rust。 思路是先实现单线程版本,尽量优化,然后多线程版本也一样。 我想实现一个我认为可能对缓存更友好的替代数据布局。 这个想法是将板上每个点的两个单元的状态存储在一个向量中,一个单元用于读取当前一代的状态,另一个用于写入下一代状态,交替访问模式每一代的计算(可以在编译时确定)。 基本数据结构如下: #[repr(u8)] pub enum CellStatus { DEAD, ALIVE, } /** 2 bytes */ pub struct CellRW(CellStatus, CellStatus); pub struct TupleBoard { width: usize, height: usize, cells: Vec<CellRW>, } /** used to keep track of current pos with iterator e.g. */ pub struct BoardPos { x_pos: usize, y_pos: usize, offset: usize, } pub struct BoardEvo { board: TupleBoard, } 给我带来麻烦的功能: impl BoardEvo { fn evolve_step<T: RWSelector>(&mut self) { for
  • Bypassing the AJAX Same-Origin Policy - A particular case
    While I was trying to refresh page contents dynamically using Ajax/JQuery, I have learned about the S-O-P issue and restrictions, however I was wondering if there could be a way to solve my little problem. To make it easier to understand I will first explain the workflow. I do receive web pages via email, that is HTML emails. The web pages contain HTML forms in such a way, once the form is complete it is sent to the proper web server (php) to store data. I mostly use Outlook 2007 as my email client (don't say anything here, I know!!!), but for some security restrictions, IFRAMES are disabled
  • 浏览器的同源策略与跨源问题
    浏览器的同源策略与跨源问题 背景 近期处理新项目调用老项目的接口时, 遇到了跨域的问题; 花费了些时间才处理好, 发现之前学得还是不够全面; 因此, 写下本篇文章进行总结; 本文内容摘要 什么是跨域, 讲述浏览器对跨域的定义为什么有跨域, 讲述浏览器为什么要限制跨域怎么能获取跨域的资源, 讲述如何规避浏览器的跨域限制 什么是跨域 说到跨域, 就需要先说一下 同源策略 同源策略是一个重要的安全策略,它用于限制一个 origin 的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。 如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。 以http://baidu.com 为例给大家举例说明 源 url: http://baidu.com同源: http://baidu.com/blog?a=1 是相同的协议(http), 端口(80), host(baidu.com)不同源: https://baidu.com 因为协议不同不同源: http://baidu.com:81 因为端口号不同不同源: http://api.baidu.com 因为域名不同 如果不同源, 那么就是跨域; 为什么有跨域 为什么浏览器要限制跨域访问? 答: 是为了安全! 如果没有了同源策略的限制
  • 绕过 AJAX 同源策略 - 一个特例(Bypassing the AJAX Same-Origin Policy - A particular case)
    问题 当我尝试使用 Ajax/JQuery 动态刷新页面内容时,我了解了 SOP 问题和限制,但是我想知道是否有办法解决我的小问题。 为了更容易理解,我将首先解释工作流程。 我确实通过电子邮件接收网页,即 HTML 电子邮件。 网页以这种方式包含 HTML 表单,一旦表单完成,它就会被发送到适当的 Web 服务器 (php) 以存储数据。 我主要使用 Outlook 2007 作为我的电子邮件客户端(这里什么都不说,我知道!!!),但出于某些安全限制,在“打开”电子邮件时禁用了 IFRAMES。 我使用 VBA 脚本绕过了这个问题,该脚本复制了整个页面内容,将其作为独立网页保存在文件系统中并加载到浏览器 (Firefox) 中。 页面加载到浏览器后,地址栏会显示本地/文件系统 URL,例如 file:///C:/Users/Bob/Desktop/outlookpage.htm 到这里没问题,工作正常; 现在的问题: 我希望使用 Ajax 动态更新页面内容,使用jQuery.load ,但这就是 SOP 的用武之地。加载以动态更新网页的 PHP 页面被视为在另一个域上运行,因此被阻止。 我想知道如何规避这一点。 回答1 这是行不通的,因为为了绕过同源策略,您需要在同一域上使用代理,然后该代理将与处理不同域上数据的页面进行通信。 无法在其他用户的计算机上生成代理脚本(或者至少
  • 将 linux 用户限制到一个文件夹(Restricting linux user to a folder)
    问题 我需要为一个用户创建一个单独的文件夹,他只能在其中执行一个二进制文件。 他也可以调用 python/perl 并运行程序。 但是用户不应该能够删除其目录中的任何文件夹,也不应该能够查看任何其他目录。 我怎样才能做到这一点? 回答1 如果他们仅通过 ssh 访问,那么ChrootDirectory是最佳选择。 简而言之,您在另一个目录中创建一个假/系统,其中包含允许用户运行的所有程序以及他们需要的库。 如果需要,请参阅sshd_config手册页的ChrootDirectory部分,或类似 Here 的地方以获得更完整的指南。 回答2 您还可以考虑配置和使用受限制的 shell ,例如受限制的 bash。 但是,请注意,如果您允许用户运行像Python这样的脚本语言,他将能够绕过这些限制(使用一些巧妙的脚本)。 所以chroot可能更可取。 您可以为该用户定义一个单独的组,以防止他做更多事情。 另请参阅 nobody 用户名、SELinux 等。 回答3 CHMOD 完成这项工作 chmod 755 directory/filename 7 user (**owner**) has full access. 5 allows **group** user "read" and "execute" permissions, but not "write" permissions
  • Why do browser APIs restrict cross-domain requests?
    XMLHttpRequests require CORS to work cross-domain. Similarly for web fonts, WebGL textures, and a few other things. In general all new APIs seem to have this restriction. Why? It's so easy to circumvent: all it takes is a simple server-side proxy. In other words, server-side code isn't prohibited from doing cross-domain requests; why is client-side code? How does this give any security, to anyone? And it's so inconsistent: I can't XMLHttpRequest, but I can <script src> or <link rel> or <img src> or <iframe>. What does restricting XHR etc. even accomplish?
  • 将我的 iOS 设备限制为特定应用(Restrict my iOS device to a particular app)
    问题 我正在寻找一种将我的 iOS 设备限制为特定应用程序的方法。 我找到了一种通过 iOS 的 Kiosk 模式禁用我的 iPad 主页按钮功能的好方法 那么是否可以在不越狱的情况下将我的 iOS 设备限制为特定的应用程序? 如果我这样做了,App-Store 会拒绝我的申请吗? 回答1 呼……终于我发现了。Guided Access 是 iOS 6 中的一项新功能,可以实现该功能。它是一个内置功能。 为特定应用程序激活引导访问,iOS 设备每次都会自动启动该应用程序。 您可以通过按住“电源+主页”按钮关闭设备。 如果您想了解如何在 iOS 6 中使用引导式访问,您可以在此处查看更多详细信息 回答2 就 App Store 而言,这是一个巨大的安全违规行为。 对于企业应用程序,您可能会找到一种方法。 但对于公开的 App Store 下载来说,这不仅几乎是不可能的,而且肯定会被拒绝。 回答3 那么是否有可能在 iPad 每次启动后自动启动我的应用程序而无需越狱? 不会。越狱只会让你弄乱系统的默认行为,例如启动项 如果我实施该行为,Apple-Store 会拒绝我的申请吗? 如果您以某种方式找到规避问题的方法(即利用安全漏洞),那么您的应用程序将被拒绝。 应用审核指南,第 2.4、2.5 节
  • 如何规避Windows Universal CRT标头对vcruntime.h的依赖(How to circumvent Windows Universal CRT headers dependency on vcruntime.h)
    问题 在尝试使用Windows Universal C运行时(... \ Windows Kits \ 10 \ Include \ 10.0.15063.0 \ ucrt)在Windows上评估Clang时,我立即面临未预料到的壁垒,形式是未公开和未预料到的依赖性在Microsoft的Visual Studio上。 显然,即使包含了任何标准C标头,即使是最简单的C程序也将无法编译,因为它们似乎都最终会尝试#include vcruntime.h(这不是UCRT的一部分)。 我的问题是: 有没有办法在没有Visual Studio的情况下利用Windows Universal C RTL SDK? 如果不希望这样做,为什么不将其称为“用于Microsoft VC的Windows CRT”-我缺少什么? 回答1 查阅[MSDN.Blogs]:介绍通用CRT(以及它引用的其他URL )。 重点是我的: 去年6月,我们发表了两篇文章,讨论了对Visual Studio 2015的Visual C ++ C运行时(CRT)所做的主要更改。 ... AppCRT和DesktopCRT已重新组合为一个库,我们将其命名为Universal CRT 。 新的DLL分别命名为ucrtbase.dll(发行版)和ucrtbased.dll(调试)。 它们不包含版本号,因为我们将就地维修它们。 来自
  • PowerShell 脚本数字签名错误(PowerShell Script digitally signed error)
    问题 运行 PowerShell 脚本时出现错误: 无法加载文件 test_new.ps1。 文件 test_new.ps1 没有数字签名。 我创建了一个 CA 和一个证书,并使用这里描述的过程签署了这个文件。 这是当我做了dir上的MY目录: EF76B3D7D8D2406E1F2EE60CC40644B122267F18 CN=PowerShell User 我可以看到附加在test_new.ps1文件末尾的签名块。 以下是执行政策和范围: Scope ExecutionPolicy ----- --------------- MachinePolicy AllSigned UserPolicy Undefined Process Bypass CurrentUser AllSigned LocalMachine Undefined machinepolicy 应优先设置为AllSigned 。 一切似乎都很好,为什么我仍然收到数字签名错误。 回答1 设置为 Allsigned 的 Powershell 执行策略仅运行由受信任发布者签名的脚本。 您可以在下面找到 -ExecutionPolicy 参数的可能值: 受限:默认设置,不加载配置文件或运行脚本。 AllSigned :要求所有脚本和配置文件都由受信任的发布者签名,包括您在本地计算机上编写的脚本。
  • android:以符号键盘模式启动,但不限于仅输入数字(android: start in symbol keyboard mode, but don't restrict to numbers-only input)
    问题 我想指定 Android 应该在数字/符号模式下为给定的 EditText 启动软键盘。 我知道这可以通过使用 EditText.setInputType() 将 EditText 的输入类型设置为数字来完成,但我不想将 EditText 的输入类型限制为仅数字输入**。 有没有另一种方法可以告诉 Android 应该为给定的 EditText 打开哪个键盘? ** 我本质上想要一个数学类的数字输入,接受任意数学表达式,包括 [0,9.+-/*()@:]。 回答1 经过一些研究并尝试了很多不同的事情,我找到了答案: editField.setRawInputType(InputType.TYPE_CLASS_NUMBER); // ^^^ note the Raw! 所以你需要设置输入类型的原始版本来规避设置的 KeyListener,这限制了输入。 回答2 我相信魔法在于: editText.setInputType(InputType.TYPE_CLASS_NUMBER);
  • 如何使用 AngularJS ngView 为未经授权的用户隐藏模板?(How to hide templates with AngularJS ngView for unauthorized users?)
    问题 我有一个基本的 PHP 应用程序,其中用户登录信息存储在 HTTP 会话中。 该应用程序有一个主模板,比如 index.html,它使用 ngView 切换子视图,如下所示 <body ng-controller='MainCtrl'> <div ng-view></div> </body> 现在,这个主模板可以通过基本的 PHP 控件来保护,但我有子模板(即用户列表、添加用户、编辑用户等),它们是纯 html 文件,根据我的路由设置从 angular 中包含。 虽然我能够检查与 http 服务请求有关的身份验证,但一位用户能够导航到子模板 url 并访问它。 我怎样才能防止这种情况发生? 回答1 我会创建这样的服务: app.factory('routeAuths', [ function() { // any path that starts with /template1 will be restricted var routeAuths = [{ path : '/template1.*', access : 'restricted' }]; return { get : function(path) { //you can expand the matching algorithm for wildcards etc. var routeAuth; for (
  • Loosen “Local procedure/function assigned to procedure variable” restriction gracefully
    Consider the following test-case: { CompilerVersion = 21 } procedure Global(); procedure Local(); begin end; type TProcedure = procedure (); var Proc: TProcedure; begin Proc := Local; { E2094 Local procedure/function 'Local' assigned to procedure variable } end; At line 13 compiler emits message with ERROR level, prohibiting all of the cases of such local procedures usage. "Official" resolution is to promote Local symbol to the outer scope (ie: make it a sibling of Global) which would have negative impact on code "structuredness". I'm seeking the way to circumvent it in most graceful manner
  • 安全性:限制第三方软件的内部访问(Security: Restrict internal access by third-party software)
    问题 我有一个Java应用程序,用户可以在其中加载第三方“插件”以增强用户体验。 这些插件可以使用API​​,但是出于安全考虑,应限制第三方软件访问内部应用程序类。 插件的受限软件包为“ com.example”,允许的软件包为“ com.example.api”。 API类确实对内部混淆类进行了调用。 经过研究之后,我遇到了SecurityManager的几种方法:checkMemberAccess(Class,int)和checkPackageAccess(String),它们似乎都是实现我目标的可行途径。 但是,在进行了一些测试和进一步的研究之后,我发现checkMemberAccess仅适用于反射调用,而checkPackageAccess仅在类加载器调用loadClass时调用。 有什么合理的方法来限制对程序包的访问(com.example,而不是com.example.api)? 回答1 我建议为插件编写一个自定义的类加载器,这对于使用该类加载器加载的类隐藏了com.example包的存在。 通常,类加载器将它们委派给其父级,但是有一些狂野的实现只能部分实现或根本不实现。 我相信例如蚂蚁会使用这种技术。 当使用这样的类加载器加载时,与禁止的功能链接的任何类都将无法加载。 或者,如果该实现使用惰性链接,并且成功加载,则在执行禁用代码期间它仍然会失败。
  • 浏览器的跨域问题以及解决方案
    1、为什么会有跨域问题的存在? JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象,即同源政策。 2、什么是同源? 1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。 最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。 (1)协议相同 (2)域名相同 (3)端口相同 具体实例 比如:http://www.example.com/zw/index.html这个网站,它的协议是http://,域名是www.example.com,端口号是80(默认端口可以省略),它的同源情况如下: ①、http://www.example.com/zwxk/manager.html 同源 ②、https://www.example.com/zw/index.html 不同源(协议不同) ③、http://examle.com/zw/index.html 不同源(域名不同) ④、http://www.example.com:81zw/index.html 不同源(端口号不同) 3、同源政策的目的 同源策略的目的是为了保证用户信息的安全。防止恶意的网站盗取数据。 设想这样一个情景:A网站是一家银行,用户登录以后,又去浏览其他的网站B,如果网站B可以读取A网站的Cookie
  • 通过成员指针访问受保护的成员:这是一种黑客行为吗?(Access to protected member through member-pointer: is it a hack?)
    问题 我们都知道从基类中指定的protected成员只能从派生类自己的实例中访问。 这是标准的一个特性,在 Stack Overflow 上已经多次讨论过: 无法从派生类型的范围访问另一个实例的受保护成员; 为什么我的对象不能访问公共基类中定义的另一个对象的受保护成员? 和别的。 但是似乎可以使用成员指针绕过这个限制,正如用户 chtz 向我展示的那样: struct Base { protected: int value; }; struct Derived : Base { void f(Base const& other) { //int n = other.value; // error: 'int Base::value' is protected within this context int n = other.*(&Derived::value); // ok??? why? (void) n; } }; 在coliru上进行现场演示 为什么这是可能的,它是实现或标准措辞中某个想要的功能还是故障? 从评论中出现了另一个问题:如果使用实际的 Base 调用 Derived::f,它是否是未定义的行为? 回答1 由于访问控制[class.access],无法使用类成员访问expr.ref ( aclass.amember
  • 如何限制在构造函数之外设置属性?(How to restrict setting an attribute outside of constructor?)
    问题 我想禁止在初始化后对类的某些属性进行进一步赋值。 例如; 在 Person 实例 'p' 初始化之后,没有人可以明确地为 'ssn'(社会安全号码)属性分配任何值。 _ setattr _在_ init _方法中赋值时也被调用,因此这不是我想要的。 我只想限制更多的分配。 我怎样才能做到这一点? class Person(object): def __init__(self, name, ssn): self.name = name self._ssn = ssn def __setattr__(self, name, value): if name == '_ssn': raise AttributeError('Denied.') else: object.__setattr__(self, name, value) >> p = Person('Ozgur', '1234') >> AttributeError: Denied. 回答1 通常的方法是使用以下划线开头的“私有”属性,以及用于公共访问的只读属性: import operator class Person(object): def __init__(self, name, ssn): self.name = name self._ssn = ssn ssn = property(operator
  • 网页限制解除(国内国外都可以使用此方法解决问题:通杀大部分网站,可以解除禁止复制、剪切、选择文本、右键菜单的限制)
    文章目录 一、问题二、解决步骤1、下载谷歌插件Tampermonkey①、能翻墙者:②、如果不能翻墙,使用我下面的方法 2、下载 (网页限制解除)的脚本 三、安装脚本成功之后,刷新下之前的网站 一、问题 (尴尬)这个很好的脚本还是我工作2年了才知道这个插件的强大功能,之前是因为不会翻墙,也没有找到这种插件镜像的网站。今天正好又遇到这种问题,就把我收藏半年之久的好用插件和一些方法分享出来(当然早就有人分享这个插件了,但是我之前下载不了,也不会弄呀)。 今天遇到一个网页不能右击,不能复制,所以通过【Tampermonkey(俗称油猴)】,在里面搜索到一个很好的脚本:(网页限制解除) 差点忘记把我遇到的这个网站忘了,你可以试试,没安装之前不能选择任何文字,不能复制,右击等操作,安装脚本之后就好了。 https://www.hack520.com/668.html 二、解决步骤 1、下载谷歌插件Tampermonkey ①、能翻墙者: 如果你的电脑可以翻墙,那么直接谷歌商店搜索:Tampermonkey,安装即可, ②、如果不能翻墙,使用我下面的方法 进入这个网站,进行下载谷歌插件,搜索这个网站我称之为插件镜像,这个网站还是我工作1年多才发现好用的网站(我不是推广这个网站或者他的公众号,只是作为一个程序员感觉很好的网站) https://www.extfans.com/
  • 由于 CORS 访问限制本地 mp3 文件,MediaElementAudioSource 输出零(MediaElementAudioSource outputs zeros due to CORS access restrictions local mp3 file)
    问题 我有以下 html 页面,我试图显示一个类,用于演示带有本地存储的 mp3 的音频可视化器: <!doctype html> <html> <head> <header name = "Access-Control-Allow-Origin" value = "*" /> <style type = "text/css"> div#mp3_player{ width: 500px; height: 60px; background: #000; padding: 5px; margin: 50px auto;} div#mp3_player > div > audio{ width: 500px; background: #000; float: left; } div#mp3_player > canvas { width: 500px; height: 30px; background: #002D3C; float: left;} </style> <script> //create new instance of audio var audio = new Audio(); audio.src = 'C:/Users/Adam/Desktop/1901.m4a'; audio.controls = true; audio.loop = true; audio