From 8094e174c3bc92f6e28aaeeda5d52f95cab8e47e Mon Sep 17 00:00:00 2001 From: Nick Carducci Date: Wed, 22 Jun 2022 09:10:32 -0400 Subject: [PATCH] Remove str-to-func eval of named function factory For support for this feature see: ttps://caniuse.com/mdn-javascript_operators_object_initializer_computed_property_names Based on #17296 --- src/embind/embind.js | 23 +++++++---------------- test/embind/embind.test.js | 11 ++++------- test/test_other.py | 19 +++++++++++++------ 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/embind/embind.js b/src/embind/embind.js index 3560ad27eae90..e45234a6da31c 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -194,25 +194,16 @@ var LibraryEmbind = { }, - // from https://github.com/imvu/imvujs/blob/master/src/function.js $createNamedFunction__deps: ['$makeLegalFunctionName'], $createNamedFunction: function(name, body) { name = makeLegalFunctionName(name); -#if DYNAMIC_EXECUTION == 0 - return function() { - "use strict"; - return body.apply(this, arguments); - }; -#else - /*jshint evil:true*/ - return new Function( - "body", - "return function " + name + "() {\n" + - " \"use strict\";" + - " return body.apply(this, arguments);\n" + - "};\n" - )(body); -#endif + // Use an abject with a computed property name to create a new function with + // a name specified at runtime, but without using `new Function` or `eval`. + return { + [name]: function() { + return body.apply(this, arguments); + } + }[name]; }, $embindRepr: function(v) { diff --git a/test/embind/embind.test.js b/test/embind/embind.test.js index 2007aa3e7a342..02f507eaea18d 100644 --- a/test/embind/embind.test.js +++ b/test/embind/embind.test.js @@ -162,17 +162,16 @@ module({ }); test("setting and getting property on unrelated class throws error", function() { - var className = cm['DYNAMIC_EXECUTION'] ? 'HasTwoBases' : ''; var a = new cm.HasTwoBases; var e = assert.throws(cm.BindingError, function() { Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').set.call(a, 10); }); - assert.equal('HeldBySmartPtr.i setter incompatible with "this" of type ' + className, e.message); + assert.equal('HeldBySmartPtr.i setter incompatible with "this" of type HasTwoBases', e.message); var e = assert.throws(cm.BindingError, function() { Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').get.call(a); }); - assert.equal('HeldBySmartPtr.i getter incompatible with "this" of type ' + className, e.message); + assert.equal('HeldBySmartPtr.i getter incompatible with "this" of type HasTwoBases', e.message); a.delete(); }); @@ -1766,8 +1765,7 @@ module({ test("smart pointer object has correct constructor name", function() { var e = new cm.HeldBySmartPtr(10, "foo"); - var expectedName = cm['DYNAMIC_EXECUTION'] ? "HeldBySmartPtr" : ""; - assert.equal(expectedName, e.constructor.name); + assert.equal("HeldBySmartPtr", e.constructor.name); e.delete(); }); @@ -2510,12 +2508,11 @@ module({ }); BaseFixture.extend("function names", function() { + assert.equal('ValHolder', cm.ValHolder.name); if (!cm['DYNAMIC_EXECUTION']) { - assert.equal('', cm.ValHolder.name); assert.equal('', cm.ValHolder.prototype.setVal.name); assert.equal('', cm.ValHolder.makeConst.name); } else { - assert.equal('ValHolder', cm.ValHolder.name); assert.equal('ValHolder$setVal', cm.ValHolder.prototype.setVal.name); assert.equal('ValHolder$makeConst', cm.ValHolder.makeConst.name); } diff --git a/test/test_other.py b/test/test_other.py index 20cb663ff1e1a..c916507d474a8 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -12370,6 +12370,13 @@ def test_es5_transpile(self, args): // arror funcs + const const bar = () => 2; err('bar: ' + bar()); + + // Computed property names + var key = 'mykey'; + var obj2 = { + [key]: 42, + }; + err('value: ' + obj2[key]); } }); ''') @@ -12403,19 +12410,19 @@ def check_for_es6(filename, expect): print('with old browser') self.emcc_args.remove('-Werror') self.set_setting('MIN_CHROME_VERSION', '10') - self.do_runf('test.c', 'prop: 1\nbar: 2\n', output_basename='test2') - check_for_es6('test2.js', False) + self.do_runf('test.c', 'prop: 1\nbar: 2\n', output_basename='test_old') + check_for_es6('test_old.js', False) # If we add `--closure=0` that transpiler (closure) is not run at all print('with old browser + --closure=0') - self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=0'], output_basename='test3') - check_for_es6('test3.js', True) + self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=0'], output_basename='test_no_closure') + check_for_es6('test_no_closure.js', True) # If we use `--closure=1` closure will run in full optimization mode # and also transpile to ES5 print('with old browser + --closure=1') - self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=1'], output_basename='test4') - check_for_es6('test4.js', False) + self.do_runf('test.c', 'prop: 1\nbar: 2\n', emcc_args=['--closure=1'], output_basename='test_closure') + check_for_es6('test_closure.js', False) def test_gmtime_noleak(self): # Confirm that gmtime_r does not leak when called in isolation.