From c788dfc3f0fe76950fb91e7747bf7343775b9900 Mon Sep 17 00:00:00 2001 From: Konrad Weihmann Date: Fri, 22 Feb 2019 14:07:42 +0100 Subject: [PATCH] Add eslint as linter for javascript Closes #10 --- .gitignore | 3 +- README.md | 21 ++- classes/sca-conv-checkstyle-eslint.bbclass | 33 +++++ .../sca-conv-checkstyle-shellcheck.bbclass | 2 +- classes/sca-eslint-core.bbclass | 74 +++++++++++ classes/sca-eslint-image.bbclass | 46 +++++++ classes/sca-eslint-recipe.bbclass | 48 +++++++ classes/sca-license-filter.bbclass | 2 +- classes/sca-on-image.bbclass | 2 +- classes/sca-on-recipe.bbclass | 2 +- ...e-running-gyp-files-for-bundled-deps.patch | 26 ++++ .../nodejs/0002-Using-native-torque.patch | 36 ++++++ ...pto-reduce-memory-usage-of-SignFinal.patch | 122 ++++++++++++++++++ ...0004-Make-compatibility-with-gcc-4.8.patch | 26 ++++ .../nodejs/0005-Link-atomic-library.patch | 20 +++ recipes-devtools/nodejs/nodejs_10.15.1.bb | 104 +++++++++++++++ .../sca-image-eslint-rules/files/fatal | 0 .../sca-image-eslint-rules/files/suppress | 0 .../sca-image-eslint-rules.bb | 21 +++ .../sca-recipe-eslint-rules/files/fatal | 3 + .../sca-recipe-eslint-rules/files/suppress | 1 + .../sca-recipe-eslint-rules.bb | 21 +++ .../eslint-native/eslint-native_5.14.1.bb | 83 ++++++++++++ .../eslint/configs/eslint-airbnb.json | 19 +++ .../eslint/configs/eslint-google.json | 19 +++ .../eslint/configs/eslint-plain.json | 19 +++ .../eslint/configs/eslint-standard.json | 19 +++ 27 files changed, 760 insertions(+), 12 deletions(-) create mode 100644 classes/sca-conv-checkstyle-eslint.bbclass create mode 100755 classes/sca-eslint-core.bbclass create mode 100755 classes/sca-eslint-image.bbclass create mode 100755 classes/sca-eslint-recipe.bbclass create mode 100644 recipes-devtools/nodejs/nodejs/0001-Disable-running-gyp-files-for-bundled-deps.patch create mode 100644 recipes-devtools/nodejs/nodejs/0002-Using-native-torque.patch create mode 100644 recipes-devtools/nodejs/nodejs/0003-Crypto-reduce-memory-usage-of-SignFinal.patch create mode 100644 recipes-devtools/nodejs/nodejs/0004-Make-compatibility-with-gcc-4.8.patch create mode 100644 recipes-devtools/nodejs/nodejs/0005-Link-atomic-library.patch create mode 100644 recipes-devtools/nodejs/nodejs_10.15.1.bb create mode 100755 recipes-sca-rules/sca-image-eslint-rules/files/fatal create mode 100755 recipes-sca-rules/sca-image-eslint-rules/files/suppress create mode 100755 recipes-sca-rules/sca-image-eslint-rules/sca-image-eslint-rules.bb create mode 100755 recipes-sca-rules/sca-recipe-eslint-rules/files/fatal create mode 100755 recipes-sca-rules/sca-recipe-eslint-rules/files/suppress create mode 100755 recipes-sca-rules/sca-recipe-eslint-rules/sca-recipe-eslint-rules.bb create mode 100644 recipes-sca/eslint-native/eslint-native_5.14.1.bb create mode 100644 recipes-sca/eslint-native/eslint/configs/eslint-airbnb.json create mode 100644 recipes-sca/eslint-native/eslint/configs/eslint-google.json create mode 100644 recipes-sca/eslint-native/eslint/configs/eslint-plain.json create mode 100644 recipes-sca/eslint-native/eslint/configs/eslint-standard.json diff --git a/.gitignore b/.gitignore index 04a80ce843..77f427ded9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -recipes-foo/foo/acl_%.bbappend -recipes-foo/foo/core-image-minimal.bbappend +recipes-foo/foo/* diff --git a/README.md b/README.md index 0496f9e876..e2f1108750 100644 --- a/README.md +++ b/README.md @@ -23,16 +23,18 @@ On the other hand some static code analysis does not make any sense on an image- ### Tools for image recipes - * pylint - * shellcheck + * pylint (python) + * shellcheck (shell) + * eslint (javascript/html) ### Tools for all other recipes - * pylint - * shellcheck + * pylint (python) + * shellcheck (shell) * gcc (getting compiler warnings/errors) - * cpplint - * cppcheck + * cpplint (c/c++) + * cppcheck (c/c++) + * eslint (javascript/html) each tool does have it's own benefits and flaws so don't be mad if you have 10k+ findings on the initial run. @@ -122,6 +124,13 @@ For further explanations on the variables see the manpage of cppcheck | SCA_SHELLCHECK_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | "" | SCA_SHELLCHECK_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | "": +### Available configuration for eslint +| var | purpose | type | default | +| ------------- |:-------------:| -----:| -----: +| SCA_ESLINT_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | "" +| SCA_ESLINT_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | "": +| SCA_ESLINT_CONFIG_FILE | Configuration-file to be used. See recipe eslint-native for details | string: eslint-standard.json, eslint-plain.json, eslint-airbnb.json, eslint-google.json | eslint-plain.json + ## Suppression and fatal-error Every tool has the possibility to suppress some of the findings. Besides that some findings could be configured to terminate the build, e.g. when a nullptr-dereference is found in C-code. diff --git a/classes/sca-conv-checkstyle-eslint.bbclass b/classes/sca-conv-checkstyle-eslint.bbclass new file mode 100644 index 0000000000..7150b0b485 --- /dev/null +++ b/classes/sca-conv-checkstyle-eslint.bbclass @@ -0,0 +1,33 @@ +## This file contains the converter from raw +## cppcheck-format to checkstyle + +inherit sca-conv-checkstyle-helper + +def do_sca_conv_eslint(d): + import os + from xml.etree.ElementTree import Element, SubElement, Comment, tostring + from xml.etree import ElementTree + from xml.dom import minidom + + package_name = d.getVar("PN", True) + buildpath = d.getVar("SCA_SOURCES_DIR", True) + + try: + data = ElementTree.ElementTree(ElementTree.parse(d.getVar("SCA_RAW_RESULT"))).getroot() + items = [] + + for f in data.findall(".//error"): + if ElementTree.tostring(f) in items or f.attrib["severity"] not in checkstyle_allowed_warning_level(d): + for h in f: + f.remove(h) + continue + items.append(ElementTree.tostring(f)) + data = data.getroot() + except Exception as e: + data = Element("checkstyle") + data.set("version", "4.3") + + try: + return checkstyle_prettify(d, data).decode("utf-8") + except: + return checkstyle_prettify(d, data) \ No newline at end of file diff --git a/classes/sca-conv-checkstyle-shellcheck.bbclass b/classes/sca-conv-checkstyle-shellcheck.bbclass index 34f91512aa..21f78b51d1 100644 --- a/classes/sca-conv-checkstyle-shellcheck.bbclass +++ b/classes/sca-conv-checkstyle-shellcheck.bbclass @@ -16,7 +16,7 @@ def do_sca_conv_shellcheck(d): data = ElementTree.ElementTree(ElementTree.parse(d.getVar("SCA_RAW_RESULT"))).getroot() items = [] - for f in data.findall(".//file"): + for f in data.findall(".//error"): if ElementTree.tostring(f) in items or f.attrib["severity"] not in checkstyle_allowed_warning_level(d): for h in f: f.remove(h) diff --git a/classes/sca-eslint-core.bbclass b/classes/sca-eslint-core.bbclass new file mode 100755 index 0000000000..60397b53c5 --- /dev/null +++ b/classes/sca-eslint-core.bbclass @@ -0,0 +1,74 @@ +inherit sca-conv-checkstyle-eslint +inherit sca-license-filter + +## Set the config file to be used - the files must be placed at ${STAGING_DATADIR_NATIVE}/eslint/configs +## See eslint-native recipe for details +SCA_ESLINT_CONFIG_FILE ?= "eslint-plain.json" +SCA_ESLINT_EXTRA_SUPPRESS ?= "" +SCA_ESLINT_EXTRA_FATAL ?= "" + +python do_prepare_recipe_sysroot_append() { + import glob + import os + + ## Rewrite all of the packages-paths if we have to + for item in glob.glob(os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint") + "/**/package.json", recursive=True): + content = "" + with open(item, "r") as i: + content = i.read().replace("%SYSROOT%", d.getVar("STAGING_DATADIR_NATIVE")) + with open(item, "w") as o: + o.write(content) +} + +DEPENDS += "nodejs-native eslint-native" + +python do_sca_eslint_core() { + import os + import subprocess + import json + + d.setVar("SCA_EXTRA_SUPPRESS", d.getVar("SCA_ESLINT_EXTRA_SUPPRESS")) + d.setVar("SCA_EXTRA_FATAL", d.getVar("SCA_ESLINT_EXTRA_FATAL")) + d.setVar("SCA_SUPRESS_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint-suppress")) + d.setVar("SCA_FATAL_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint-fatal")) + + _supress = get_suppress_entries(d) + _fatal = get_fatal_entries(d) + + _args = [os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint", "node_modules", ".bin", "eslint")] + _args += ["-c", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "eslint", "configs", d.getVar("SCA_ESLINT_CONFIG_FILE"))] + _args += ["-f", "checkstyle"] + _args += ["--quiet"] + _args += [d.getVar("SCA_SOURCES_DIR") + "/"] + + cmd_output = "" + try: + cmd_output = subprocess.check_output(_args, universal_newlines=True) + except subprocess.CalledProcessError as e: + cmd_output = e.stdout or "" + result_raw_file = os.path.join(d.getVar("T"), "sca_raw_eslint.xml") + d.setVar("SCA_RAW_RESULT", result_raw_file) + with open(result_raw_file, "w") as o: + o.write(cmd_output) + xml_output = do_sca_conv_eslint(d) + result_file = os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml") + d.setVar("SCA_RESULT_FILE", result_file) + with open(result_file, "w") as o: + o.write(xml_output) + + ## Evaluate + _warnings = get_warnings_from_result(d) + _fatals = get_fatal_from_result(d, "eslint.", _fatal) + _errors = get_errors_from_result(d) + + warn_log = [] + if any(_warnings): + warn_log.append("{} warning(s)".format(len(_warnings))) + if any(_errors): + warn_log.append("{} error(s)".format(len(_errors))) + if warn_log: + bb.warn("SCA has found {}".format(",".join(warn_log))) + + if any(_fatals): + bb.fatal("SCA has following fatal errors: {}".format("\n".join(_fatals))) +} diff --git a/classes/sca-eslint-image.bbclass b/classes/sca-eslint-image.bbclass new file mode 100755 index 0000000000..f4b68b2c7f --- /dev/null +++ b/classes/sca-eslint-image.bbclass @@ -0,0 +1,46 @@ +inherit sca-helper +inherit sca-global +inherit sca-eslint-core +inherit sca-conv-checkstyle-helper + +python do_sca_deploy_eslint_image() { + import os + import shutil + + os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw"), exist_ok=True) + os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle"), exist_ok=True) + + import os + from xml.etree.ElementTree import Element, SubElement, Comment, tostring + from xml.etree import ElementTree + from xml.dom import minidom + + for _file in ["sca_raw_eslint.xml", "sca_checkstyle_eslint.xml"]: + if not os.path.exists(os.path.join(d.getVar("T"), _file)): + continue + data = ElementTree.parse(os.path.join(d.getVar("T"), _file)).getroot() + for node in data.findall(".//error"): + ## Patch to common format + node.attrib["message"] = "[Package:'{}' Tool:eslint] {}".format(d.getVar("PN"), node.attrib["message"]) + node.attrib["source"] = "ShellCheck.{}".format(node.attrib["source"]) + + res = "" + try: + res = checkstyle_prettify(d, data).decode("utf-8") + except: + res = checkstyle_prettify(d, data) + with open(os.path.join(d.getVar("T"), _file), "w") as f: + f.write(res) + + raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV"))) + cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV"))) + shutil.copy(os.path.join(d.getVar("T"), "sca_raw_eslint.xml"), raw_target) + shutil.copy(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml"), cs_target) + + do_sca_export_sources(d, cs_target) +} + +addtask do_sca_eslint_core before before do_image_complete after do_image +addtask do_sca_deploy_eslint_image before do_image_complete after do_sca_eslint_core + +DEPENDS += "sca-image-eslint-rules-native" diff --git a/classes/sca-eslint-recipe.bbclass b/classes/sca-eslint-recipe.bbclass new file mode 100755 index 0000000000..529aded04a --- /dev/null +++ b/classes/sca-eslint-recipe.bbclass @@ -0,0 +1,48 @@ +inherit sca-helper +inherit sca-global +inherit sca-eslint-core + +python do_sca_deploy_eslint_recipe() { + import os + import shutil + + os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw"), exist_ok=True) + os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle"), exist_ok=True) + + import os + from xml.etree.ElementTree import Element, SubElement, Comment, tostring + from xml.etree import ElementTree + from xml.dom import minidom + + for _file in ["sca_raw_eslint.xml", "sca_checkstyle_eslint.xml"]: + try: + data = ElementTree.parse(os.path.join(d.getVar("T"), _file)).getroot() + for node in data.findall(".//error"): + ## Patch to common format + node.attrib["message"] = "[Package:'{}' Tool:eslint] {}".format(d.getVar("PN"), node.attrib["message"]) + node.attrib["source"] = "eslint.{}".format(node.attrib["source"]) + + res = "" + try: + res = prettify(top).decode("utf-8") + except: + res = prettify(top) + with open(os.path.join(d.getVar("T"), _file), "w") as f: + f.write(res) + except: + pass + + raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "raw", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV"))) + cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "eslint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV"))) + if os.path.exists(os.path.join(d.getVar("T"), "sca_raw_eslint.xml")): + shutil.copy(os.path.join(d.getVar("T"), "sca_raw_eslint.xml"), raw_target) + if os.path.exists(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml")): + shutil.copy(os.path.join(d.getVar("T"), "sca_checkstyle_eslint.xml"), cs_target) + + do_sca_export_sources(d, cs_target) +} + +addtask do_sca_eslint_core before do_install after do_compile +addtask do_sca_deploy_eslint_recipe before do_package after do_sca_eslint_core + +DEPENDS += "sca-recipe-eslint-rules-native" diff --git a/classes/sca-license-filter.bbclass b/classes/sca-license-filter.bbclass index 3d22a0214e..8384b416c3 100644 --- a/classes/sca-license-filter.bbclass +++ b/classes/sca-license-filter.bbclass @@ -45,7 +45,7 @@ def sca_filter_by_license_image(d, licenses): return list(set(ignores)) def sca_filter_by_license_recipe(d, licenses): - if d.getVar("LICENSE") in licenses: + if not d.getVar("LICENSE") in licenses: return [] return [ 1 ] ## return dummy value diff --git a/classes/sca-on-image.bbclass b/classes/sca-on-image.bbclass index 5453be3954..d739ee2d60 100755 --- a/classes/sca-on-image.bbclass +++ b/classes/sca-on-image.bbclass @@ -3,7 +3,7 @@ inherit sca-global SCA_PACKAGE_LICENSE_FILTER = "CLOSED" -SCA_ENABLED_MODULES ?= "shellcheck pylint" +SCA_ENABLED_MODULES ?= "eslint pylint shellcheck" SCA_SOURCES_DIR ?= "${IMAGE_ROOTFS}" SCA_MODE = "image" diff --git a/classes/sca-on-recipe.bbclass b/classes/sca-on-recipe.bbclass index 73102d3502..edf10d1136 100755 --- a/classes/sca-on-recipe.bbclass +++ b/classes/sca-on-recipe.bbclass @@ -3,7 +3,7 @@ inherit sca-global inherit sca-license-filter -SCA_ENABLED_MODULES ?= "gcc cpplint cppcheck pylint shellcheck" +SCA_ENABLED_MODULES ?= "eslint cpplint cppcheck gcc pylint shellcheck" SCA_SOURCES_DIR ?= "${B}" SCA_MODE = "recipe" diff --git a/recipes-devtools/nodejs/nodejs/0001-Disable-running-gyp-files-for-bundled-deps.patch b/recipes-devtools/nodejs/nodejs/0001-Disable-running-gyp-files-for-bundled-deps.patch new file mode 100644 index 0000000000..5d0dc03b66 --- /dev/null +++ b/recipes-devtools/nodejs/nodejs/0001-Disable-running-gyp-files-for-bundled-deps.patch @@ -0,0 +1,26 @@ +From c2aff16cc196a61f4ab1cdae4a91c7926123c239 Mon Sep 17 00:00:00 2001 +From: Zuzana Svetlikova +Date: Thu, 27 Apr 2017 14:25:42 +0200 +Subject: [PATCH] Disable running gyp on shared deps + +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index a98772f..f5663e2 100644 +--- a/Makefile ++++ b/Makefile +@@ -123,8 +123,8 @@ with-code-cache: + test-code-cache: with-code-cache + $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) code-cache + +-out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp \ +- deps/zlib/zlib.gyp deps/v8/gypfiles/toolchain.gypi \ ++out/Makefile: common.gypi deps/http_parser/http_parser.gyp \ ++ deps/v8/gypfiles/toolchain.gypi \ + deps/v8/gypfiles/features.gypi deps/v8/gypfiles/v8.gyp node.gyp \ + config.gypi + $(PYTHON) tools/gyp_node.py -f make +-- +2.19.2 diff --git a/recipes-devtools/nodejs/nodejs/0002-Using-native-torque.patch b/recipes-devtools/nodejs/nodejs/0002-Using-native-torque.patch new file mode 100644 index 0000000000..e9035f9eb3 --- /dev/null +++ b/recipes-devtools/nodejs/nodejs/0002-Using-native-torque.patch @@ -0,0 +1,36 @@ +From 4bbee5e3d58bc4911999f3ec2cc5aab8ded6717b Mon Sep 17 00:00:00 2001 +From: "Winker Matthias (TT-CA/ENG1)" +Date: Tue, 11 Dec 2018 10:44:29 +0100 +Subject: [PATCH] Using native torque + +--- + deps/v8/gypfiles/v8.gyp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/deps/v8/gypfiles/v8.gyp b/deps/v8/gypfiles/v8.gyp +index 8c78f02255..434168844e 100644 +--- a/deps/v8/gypfiles/v8.gyp ++++ b/deps/v8/gypfiles/v8.gyp +@@ -2831,7 +2831,6 @@ + { + 'action_name': 'run_torque', + 'inputs': [ # Order matters. +- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)torque<(EXECUTABLE_SUFFIX)', + '../src/builtins/base.tq', + '../src/builtins/array.tq', + '../src/builtins/typed-array.tq', +@@ -2845,7 +2844,10 @@ + '<(SHARED_INTERMEDIATE_DIR)/torque-generated/builtins-typed-array-from-dsl-gen.cc', + '<(SHARED_INTERMEDIATE_DIR)/torque-generated/builtins-typed-array-from-dsl-gen.h', + ], +- 'action': ['<@(_inputs)', '-o', '<(SHARED_INTERMEDIATE_DIR)/torque-generated'], ++ 'action': [ ++ 'torque', ++ '<@(_inputs)', ++ '-o', '<(SHARED_INTERMEDIATE_DIR)/torque-generated'], + }, + ], + }, # torque +-- +2.19.2 + diff --git a/recipes-devtools/nodejs/nodejs/0003-Crypto-reduce-memory-usage-of-SignFinal.patch b/recipes-devtools/nodejs/nodejs/0003-Crypto-reduce-memory-usage-of-SignFinal.patch new file mode 100644 index 0000000000..ed3bac39bd --- /dev/null +++ b/recipes-devtools/nodejs/nodejs/0003-Crypto-reduce-memory-usage-of-SignFinal.patch @@ -0,0 +1,122 @@ +From 20282b1cb0389553421c4c5b14de198c5dfff50b Mon Sep 17 00:00:00 2001 +From: Anna Henningsen +Date: Sat, 20 Oct 2018 05:24:54 +0200 +Subject: [PATCH] src: use more explicit return type in Sign::SignFinal() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Using the non-indexed variant of `std::get<>` broke Travis CI. +Also, this allows us to be a bit more concise when returning +from `SignFinal()` due to some error condition. + +Refs: https://github.com/nodejs/node/pull/23427 + +PR-URL: https://github.com/nodejs/node/pull/23779 +Reviewed-By: Joyee Cheung +Reviewed-By: Tobias Nießen +Reviewed-By: Refael Ackermann +Reviewed-By: Colin Ihrig +--- + src/node_crypto.cc | 23 +++++++++++------------ + src/node_crypto.h | 12 +++++++++++- + 2 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/src/node_crypto.cc b/src/node_crypto.cc +index bd8d9e032554..ec7d4f2bb5be 100644 +--- a/src/node_crypto.cc ++++ b/src/node_crypto.cc +@@ -3562,22 +3562,20 @@ static MallocedBuffer Node_SignFinal(EVPMDPointer&& mdctx, + return MallocedBuffer(); + } + +-std::pair> Sign::SignFinal( ++Sign::SignResult Sign::SignFinal( + const char* key_pem, + int key_pem_len, + const char* passphrase, + int padding, + int salt_len) { +- MallocedBuffer buffer; +- + if (!mdctx_) +- return std::make_pair(kSignNotInitialised, std::move(buffer)); ++ return SignResult(kSignNotInitialised); + + EVPMDPointer mdctx = std::move(mdctx_); + + BIOPointer bp(BIO_new_mem_buf(const_cast(key_pem), key_pem_len)); + if (!bp) +- return std::make_pair(kSignPrivateKey, std::move(buffer)); ++ return SignResult(kSignPrivateKey); + + EVPKeyPointer pkey(PEM_read_bio_PrivateKey(bp.get(), + nullptr, +@@ -3588,7 +3586,7 @@ std::pair> Sign::SignFinal( + // without `pkey` being set to nullptr; + // cf. the test of `test_bad_rsa_privkey.pem` for an example. + if (!pkey || 0 != ERR_peek_error()) +- return std::make_pair(kSignPrivateKey, std::move(buffer)); ++ return SignResult(kSignPrivateKey); + + #ifdef NODE_FIPS_MODE + /* Validate DSA2 parameters from FIPS 186-4 */ +@@ -3612,9 +3610,10 @@ std::pair> Sign::SignFinal( + } + #endif // NODE_FIPS_MODE + +- buffer = Node_SignFinal(std::move(mdctx), pkey, padding, salt_len); ++ MallocedBuffer buffer = ++ Node_SignFinal(std::move(mdctx), pkey, padding, salt_len); + Error error = buffer.is_empty() ? kSignPrivateKey : kSignOk; +- return std::make_pair(error, std::move(buffer)); ++ return SignResult(error, std::move(buffer)); + } + + +@@ -3639,18 +3638,18 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) { + + ClearErrorOnReturn clear_error_on_return; + +- std::pair> ret = sign->SignFinal( ++ SignResult ret = sign->SignFinal( + buf, + buf_len, + len >= 2 && !args[1]->IsNull() ? *passphrase : nullptr, + padding, + salt_len); + +- if (std::get(ret) != kSignOk) +- return sign->CheckThrow(std::get(ret)); ++ if (ret.error != kSignOk) ++ return sign->CheckThrow(ret.error); + + MallocedBuffer sig = +- std::move(std::get>(ret)); ++ std::move(ret.signature); + + Local rc = + Buffer::New(env, reinterpret_cast(sig.release()), sig.size) +diff --git a/src/node_crypto.h b/src/node_crypto.h +index 6fcf737f6c43..0c26c1f6ff1d 100644 +--- a/src/node_crypto.h ++++ b/src/node_crypto.h +@@ -518,7 +518,17 @@ class Sign : public SignBase { + public: + static void Initialize(Environment* env, v8::Local target); + +- std::pair> SignFinal( ++ struct SignResult { ++ Error error; ++ MallocedBuffer signature; ++ ++ explicit SignResult( ++ Error err, ++ MallocedBuffer&& sig = MallocedBuffer()) ++ : error(err), signature(std::move(sig)) {} ++ }; ++ ++ SignResult SignFinal( + const char* key_pem, + int key_pem_len, + const char* passphrase, diff --git a/recipes-devtools/nodejs/nodejs/0004-Make-compatibility-with-gcc-4.8.patch b/recipes-devtools/nodejs/nodejs/0004-Make-compatibility-with-gcc-4.8.patch new file mode 100644 index 0000000000..2b325b675f --- /dev/null +++ b/recipes-devtools/nodejs/nodejs/0004-Make-compatibility-with-gcc-4.8.patch @@ -0,0 +1,26 @@ +Implement function as wrapper for std::make_unique +method to be compatible with gcc < 4.9 . +"error::make_unique is not a member of 'std'" + +Signed-off-by: Andrej Valek + +diff -Naur node-v10.15.1/src/cares_wrap.cc node-v10.15.1/src/cares_wrap.cc +--- node-v10.15.1/src/cares_wrap.cc 2019-02-17 09:40:36.040538319 +0100 ++++ node-v10.15.1/src/cares_wrap.cc 2019-02-17 09:39:57.883668702 +0100 +@@ -52,6 +52,16 @@ + # define AI_V4MAPPED 0 + #endif + ++#ifndef __cpp_lib_make_unique ++ namespace std { ++ /// make_unique implementation ++ template ++ std::unique_ptr make_unique(Args&&... args) { ++ return std::unique_ptr(new T(std::forward(args)...)); ++ } ++ } ++#endif ++ + namespace node { + namespace cares_wrap { + diff --git a/recipes-devtools/nodejs/nodejs/0005-Link-atomic-library.patch b/recipes-devtools/nodejs/nodejs/0005-Link-atomic-library.patch new file mode 100644 index 0000000000..66ff18b4a3 --- /dev/null +++ b/recipes-devtools/nodejs/nodejs/0005-Link-atomic-library.patch @@ -0,0 +1,20 @@ +Link atomic library to fix missing undefined referrences +like "undefined reference to `__atomic_fetch_add_8'" + +Signed-off-by: Andrej Valek + +diff -Naur node-v10.15.1/deps/v8/gypfiles/v8.gyp node-v10.15.1/deps/v8/gypfiles/v8.gyp +--- node-v10.15.1/deps/v8/gypfiles/v8.gyp 2019-02-13 09:02:21.000000000 +0100 ++++ node-v10.15.1/deps/v8/gypfiles/v8.gyp 2019-02-15 21:27:11.755679660 +0100 +@@ -452,6 +452,11 @@ + '<(DEPTH)', + '<(SHARED_INTERMEDIATE_DIR)' + ], ++ 'link_settings': { ++ 'libraries': [ ++ '-latomic' ++ ], ++ }, + 'sources': [ + '<@(inspector_all_sources)', + '../include//v8-inspector-protocol.h', diff --git a/recipes-devtools/nodejs/nodejs_10.15.1.bb b/recipes-devtools/nodejs/nodejs_10.15.1.bb new file mode 100644 index 0000000000..17c9bb0c4e --- /dev/null +++ b/recipes-devtools/nodejs/nodejs_10.15.1.bb @@ -0,0 +1,104 @@ +DESCRIPTION = "nodeJS Evented I/O for V8 JavaScript" +HOMEPAGE = "http://nodejs.org" +LICENSE = "MIT & BSD & Artistic-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=9ceeba79eb2ea1067b7b3ed16fff8bab" + +DEPENDS = "openssl zlib icu" +DEPENDS_append_class-target = " nodejs-native" + +inherit pkgconfig + +COMPATIBLE_MACHINE_armv4 = "(!.*armv4).*" +COMPATIBLE_MACHINE_armv5 = "(!.*armv5).*" +COMPATIBLE_MACHINE_mips64 = "(!.*mips64).*" + +SRC_URI = "http://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \ + file://0001-Disable-running-gyp-files-for-bundled-deps.patch \ + file://0003-Crypto-reduce-memory-usage-of-SignFinal.patch \ + file://0004-Make-compatibility-with-gcc-4.8.patch \ + file://0005-Link-atomic-library.patch \ + " +SRC_URI_append_class-target = " \ + file://0002-Using-native-torque.patch \ + " + +SRC_URI[md5sum] = "1cad7963255de53509bfa560221bdc88" +SRC_URI[sha256sum] = "1a55f7b9fb80442182d9e1eba4fca4dac3c781cdcb25d6be37b24d253f61c858" + +S = "${WORKDIR}/node-v${PV}" + +# v8 errors out if you have set CCACHE +CCACHE = "" + +def map_nodejs_arch(a, d): + import re + + if re.match('i.86$', a): return 'ia32' + elif re.match('x86_64$', a): return 'x64' + elif re.match('aarch64$', a): return 'arm64' + elif re.match('(powerpc64|ppc64le)$', a): return 'ppc64' + elif re.match('powerpc$', a): return 'ppc' + return a + +ARCHFLAGS_arm = "${@bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', '--with-arm-float-abi=hard', '--with-arm-float-abi=softfp', d)} \ + ${@bb.utils.contains('TUNE_FEATURES', 'neon', '--with-arm-fpu=neon', \ + bb.utils.contains('TUNE_FEATURES', 'vfpv3d16', '--with-arm-fpu=vfpv3-d16', \ + bb.utils.contains('TUNE_FEATURES', 'vfpv3', '--with-arm-fpu=vfpv3', \ + '--with-arm-fpu=vfp', d), d), d)}" +GYP_DEFINES_append_mipsel = " mips_arch_variant='r1' " +ARCHFLAGS ?= "" + +# Node is way too cool to use proper autotools, so we install two wrappers to forcefully inject proper arch cflags to workaround gypi +do_configure () { + rm -rf ${S}/deps/openssl + export LD="${CXX}" + GYP_DEFINES="${GYP_DEFINES}" export GYP_DEFINES + # $TARGET_ARCH settings don't match --dest-cpu settings + ./configure --prefix=${prefix} --with-intl=system-icu --without-snapshot --shared-openssl --shared-zlib \ + --dest-cpu="${@map_nodejs_arch(d.getVar('TARGET_ARCH'), d)}" \ + --dest-os=linux \ + ${ARCHFLAGS} +} + +do_compile () { + export LD="${CXX}" + oe_runmake BUILDTYPE=Release +} + +do_install () { + oe_runmake install DESTDIR=${D} +} + +do_install_append_class-native() { + # use node from PATH instead of absolute path to sysroot + # node-v0.10.25/tools/install.py is using: + # shebang = os.path.join(node_prefix, 'bin/node') + # update_shebang(link_path, shebang) + # and node_prefix can be very long path to bindir in native sysroot and + # when it exceeds 128 character shebang limit it's stripped to incorrect path + # and npm fails to execute like in this case with 133 characters show in log.do_install: + # updating shebang of /home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/work/x86_64-linux/nodejs-native/0.10.15-r0/image/home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/sysroots/x86_64-linux/usr/bin/npm to /home/jenkins/workspace/build-webos-nightly/device/qemux86/label/open-webos-builder/BUILD-qemux86/sysroots/x86_64-linux/usr/bin/node + # /usr/bin/npm is symlink to /usr/lib/node_modules/npm/bin/npm-cli.js + # use sed on npm-cli.js because otherwise symlink is replaced with normal file and + # npm-cli.js continues to use old shebang + sed "1s^.*^#\!/usr/bin/env node^g" -i ${D}${exec_prefix}/lib/node_modules/npm/bin/npm-cli.js + + # Install the native torque to provide it within sysroot for the target compilation + install -d ${D}${bindir} + install -m 0755 ${S}/out/Release/torque ${D}${bindir}/torque +} + +do_install_append_class-target() { + sed "1s^.*^#\!${bindir}/env node^g" -i ${D}${exec_prefix}/lib/node_modules/npm/bin/npm-cli.js +} + +PACKAGES =+ "${PN}-npm" +FILES_${PN}-npm = "${exec_prefix}/lib/node_modules ${bindir}/npm ${bindir}/npx" +RDEPENDS_${PN}-npm = "bash python-shell python-datetime python-subprocess python-textutils \ + python-compiler python-misc python-multiprocessing" + +PACKAGES =+ "${PN}-systemtap" +FILES_${PN}-systemtap = "${datadir}/systemtap" + + +BBCLASSEXTEND = "native" diff --git a/recipes-sca-rules/sca-image-eslint-rules/files/fatal b/recipes-sca-rules/sca-image-eslint-rules/files/fatal new file mode 100755 index 0000000000..e69de29bb2 diff --git a/recipes-sca-rules/sca-image-eslint-rules/files/suppress b/recipes-sca-rules/sca-image-eslint-rules/files/suppress new file mode 100755 index 0000000000..e69de29bb2 diff --git a/recipes-sca-rules/sca-image-eslint-rules/sca-image-eslint-rules.bb b/recipes-sca-rules/sca-image-eslint-rules/sca-image-eslint-rules.bb new file mode 100755 index 0000000000..35c4ec4193 --- /dev/null +++ b/recipes-sca-rules/sca-image-eslint-rules/sca-image-eslint-rules.bb @@ -0,0 +1,21 @@ +SUMMARY = "Ruleset for eslint" +DESCRIPTION = " Rules to configure how eslint is affecting the build" + +SRC_URI = "file://suppress \ + file://fatal" + +LICENSE ?= "BSD-2-Clause" +LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/BSD-2-Clause;md5=8bef8e6712b1be5aa76af1ebde9d6378" + +BBCLASSEXTEND = "native" + +## Don't cache - always make it clean +BB_DONT_CACHE = "1" + +do_install() { + install -d "${D}${datadir}" + install "${WORKDIR}/suppress" "${D}${datadir}/eslint-suppress" + install "${WORKDIR}/fatal" "${D}${datadir}/eslint-fatal" +} + +FILES_${PN} = "${datadir}/**" \ No newline at end of file diff --git a/recipes-sca-rules/sca-recipe-eslint-rules/files/fatal b/recipes-sca-rules/sca-recipe-eslint-rules/files/fatal new file mode 100755 index 0000000000..afa966b050 --- /dev/null +++ b/recipes-sca-rules/sca-recipe-eslint-rules/files/fatal @@ -0,0 +1,3 @@ +1000 +1007 +1048 \ No newline at end of file diff --git a/recipes-sca-rules/sca-recipe-eslint-rules/files/suppress b/recipes-sca-rules/sca-recipe-eslint-rules/files/suppress new file mode 100755 index 0000000000..e4028df9c1 --- /dev/null +++ b/recipes-sca-rules/sca-recipe-eslint-rules/files/suppress @@ -0,0 +1 @@ + 1091 \ No newline at end of file diff --git a/recipes-sca-rules/sca-recipe-eslint-rules/sca-recipe-eslint-rules.bb b/recipes-sca-rules/sca-recipe-eslint-rules/sca-recipe-eslint-rules.bb new file mode 100755 index 0000000000..35c4ec4193 --- /dev/null +++ b/recipes-sca-rules/sca-recipe-eslint-rules/sca-recipe-eslint-rules.bb @@ -0,0 +1,21 @@ +SUMMARY = "Ruleset for eslint" +DESCRIPTION = " Rules to configure how eslint is affecting the build" + +SRC_URI = "file://suppress \ + file://fatal" + +LICENSE ?= "BSD-2-Clause" +LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/BSD-2-Clause;md5=8bef8e6712b1be5aa76af1ebde9d6378" + +BBCLASSEXTEND = "native" + +## Don't cache - always make it clean +BB_DONT_CACHE = "1" + +do_install() { + install -d "${D}${datadir}" + install "${WORKDIR}/suppress" "${D}${datadir}/eslint-suppress" + install "${WORKDIR}/fatal" "${D}${datadir}/eslint-fatal" +} + +FILES_${PN} = "${datadir}/**" \ No newline at end of file diff --git a/recipes-sca/eslint-native/eslint-native_5.14.1.bb b/recipes-sca/eslint-native/eslint-native_5.14.1.bb new file mode 100644 index 0000000000..ac0a1cca02 --- /dev/null +++ b/recipes-sca/eslint-native/eslint-native_5.14.1.bb @@ -0,0 +1,83 @@ +SUMMARY = "Native variant of eslint" +DESCRIPTION = "Native build of eslint." + +SRC_URI = "file://configs/*" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +do_configure[noexec] = "1" + +DEPENDS += "nodejs-native" + +FILES_${PN} = "${datadir}/" + +inherit native + +python do_compile() { + import json + import os + import subprocess + + ## Create fake package-config + pkg = { + "name": "Foo", + "version": "1.0.0", + "description": "Bar", + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT" + } + + with open("package.json", "w") as i: + json.dump(pkg, i) + + ## Install needed pkgs + pkgs = [ + "eslint@{}".format(d.getVar("PV")), + "eslint-config-airbnb-base@latest", + "eslint-config-google@latest", + "eslint-config-standard@latest", + "eslint-plugin-html@5.0.3", + "eslint-plugin-import@>=2.13.0", + "eslint-plugin-node@>=7.0.0", + "eslint-plugin-promise@>=4.0.0", + "eslint-plugin-react@latest", + "eslint-plugin-standard@>=4.0.0", + "eslint-plugin-vue@latest", + "@satazor/eslint-config@latest", + "@ljharb/eslint-config@latest" + ] + + for pkg in pkgs: + try: + subprocess.check_call(["npm", "install", pkg, "--save-dev"], universal_newlines=True) + except subprocess.CalledProcessError as e: + bb.error("Install of NPM package {} failed".format(pkg)) + + ## Strip of hardcoded paths in packages + import os + for folder, dirs, files in os.walk(d.getVar("B")): + for _file in files: + if _file.endswith('.json'): + fullpath = os.path.join(folder, _file) + content = "" + with open(fullpath, 'r') as f: + content = f.read().replace(d.getVar("B"), "%SYSROOT%/eslint") + with open(fullpath, "w") as f: + f.write(content) +} + +INSANE_SKIP_${PN} += "host-user-contaminated" + +do_install() { + mkdir -p ${D}${datadir}/eslint/configs + cp -Ra ${B}/* ${D}${datadir}/eslint + cp -a ${WORKDIR}/configs/* ${D}${datadir}/eslint/configs +} + diff --git a/recipes-sca/eslint-native/eslint/configs/eslint-airbnb.json b/recipes-sca/eslint-native/eslint/configs/eslint-airbnb.json new file mode 100644 index 0000000000..0d01c8d5ca --- /dev/null +++ b/recipes-sca/eslint-native/eslint/configs/eslint-airbnb.json @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "plugins": [ + "html" + ], + "extends": [ "eslint:recommended", "airbnb-base"], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + } +} \ No newline at end of file diff --git a/recipes-sca/eslint-native/eslint/configs/eslint-google.json b/recipes-sca/eslint-native/eslint/configs/eslint-google.json new file mode 100644 index 0000000000..8c6b683477 --- /dev/null +++ b/recipes-sca/eslint-native/eslint/configs/eslint-google.json @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "plugins": [ + "html" + ], + "extends": [ "eslint:recommended", "google"], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + } +} \ No newline at end of file diff --git a/recipes-sca/eslint-native/eslint/configs/eslint-plain.json b/recipes-sca/eslint-native/eslint/configs/eslint-plain.json new file mode 100644 index 0000000000..93875f51fc --- /dev/null +++ b/recipes-sca/eslint-native/eslint/configs/eslint-plain.json @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "plugins": [ + "html" + ], + "extends": [ "eslint:recommended" ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + } +} \ No newline at end of file diff --git a/recipes-sca/eslint-native/eslint/configs/eslint-standard.json b/recipes-sca/eslint-native/eslint/configs/eslint-standard.json new file mode 100644 index 0000000000..40e84c2adf --- /dev/null +++ b/recipes-sca/eslint-native/eslint/configs/eslint-standard.json @@ -0,0 +1,19 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "plugins": [ + "html" + ], + "extends": [ "standard"], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + } +} \ No newline at end of file