【问题标题】:core-js/babel-polyfill polyfilled functions appear as [native code]core-js/babel-polyfill 填充函数显示为 [native code]
【发布时间】:2017-02-06 00:35:32
【问题描述】:

使用 core-js 填充的函数(例如,babel-polyfill)显示为原生函数。

Promise.race.toString() 产生:

function race() {
    [native code]
}

Object.values.toString() 也是如此。

虽然它们肯定不是浏览器的原生实现。示例为Babel REPL 页面。

开发人员如何以编程方式检查函数不是原生实现,而是模仿原生函数的 polyfill(例如,当已知特定的 polyfill 可能导致应用程序出现问题时)?

通常native code 正则表达式会有所帮助,但肯定不是这样。

如何从这些函数中检索源代码?我主要对 Node.js 感兴趣,但欢迎跨平台解决方案。

这个技巧到底是怎么做到的?我在core-jsbabel-polyfill 源代码中找不到任何native code 搜索。

【问题讨论】:

    标签: javascript node.js babeljs babel-polyfill


    【解决方案1】:

    core-js 尝试通过将 Function.prototype.toString here 替换为默认版本来使其 polyfill 功能显示为原生实现,但允许 core-js 通过设置值为fn[SRC]

    你可以在here它分配fn[SRC]的那个文件中看到更远的地方,特别是

    if(isFunction)has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
    

    如果您检查TPL,在这种情况下它是["function ", "() { [native code] }"],所以当使用.join(String(key)) 调用时,您最终会得到

    function race() { [native code] }
    

    你在输出中看到的。

    【讨论】:

    • 太好了,这就解释了为什么我试过Promise.race.toString = Function.toString 没有效果。
    • 你对问题的另一部分有什么想法,如何测试一个函数是否被填充?我猜你是贡献者之一,不是吗?
    • 不幸的是,我认为这是一件非常困难的事情。如果您可以在加载 core-js 之前获得对 Function.prototype.toString 的引用,那将是最简单的。您能否详细说明您要检测它的目的是什么?我贡献了一些东西,但我主要关注 Babel,所以我也不是专家。
    • 刚刚注意到填充函数中的“SRC”属性。看起来没有其他方法,这就是我一直在寻找的。我的环境不太适合调试,并且浪费了一些时间来调查为什么 Bluebird Promise 不存在以及为什么存在“本机”承诺(某些依赖项已在安静状态下加载了 babel-polyfill)。我不会让这种事再发生在我身上。谢谢,_redefine.js 正是我需要的地方。
    • 似乎包含TPL的语句没有使用返回值。那么这是如何工作的呢?
    【解决方案2】:

    Polyfilled core-js 函数具有 unique property which is defined by the library 并存储在内部,如 Symbol(src)_1.g50a4eqv8s8xgvi。这允许图书馆识别它们并伪造toString() 结果(正如另一个答案彻底解释的那样)。

    可以检测唯一属性并欺骗core-js进入真实的函数体:

    function getPolyfillUid(fn) {
        return Object.getOwnPropertyNames(fn).find(prop => /^Symbol\(.+\)_/.test(prop))
    }
    
    function toTrueString(fn) {
        const uid = getPolyfillUid(fn);
        let fnString;
        if (uid) {
            const uidDescriptor = Object.getOwnPropertyDescriptor(fn, uid);
            delete fn[uid];
            fnString = fn.toString();
            Object.defineProperty(fn, uid, uidDescriptor);
        } else {
            fnString = fn.toString();
        }
    
        return fnString;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 2019-08-20
      • 2022-10-14
      • 2015-10-09
      • 1970-01-01
      相关资源
      最近更新 更多