diff --git a/darwin/ninja.exe b/darwin/ninja.exe index 23a29c7378..969426bd0a 100755 Binary files a/darwin/ninja.exe and b/darwin/ninja.exe differ diff --git a/darwinarm64/ninja.exe b/darwinarm64/ninja.exe index 0b60a3cb61..2d72eff8af 100755 Binary files a/darwinarm64/ninja.exe and b/darwinarm64/ninja.exe differ diff --git a/jscomp/bsb_helper/bsb_helper_depfile_gen.ml b/jscomp/bsb_helper/bsb_helper_depfile_gen.ml index f34b6e3f25..2edb2e7a7f 100644 --- a/jscomp/bsb_helper/bsb_helper_depfile_gen.ml +++ b/jscomp/bsb_helper/bsb_helper_depfile_gen.ml @@ -105,6 +105,11 @@ let oc_cmi buf namespace source = When ns is turned on, `B` is interprted as `Ns-B` which is a cyclic dependency, it can be errored out earlier + + #5368: It turns out there are many false positives on detecting self-cycles (see: `jscomp/build_tests/zerocycle`) + To properly solve this, we would need to `jscomp/ml/depend.ml` because + cmi and cmj is broken in the first place (same problem as in ocaml/ocaml#4618). + So we will just ignore the self-cycles. Even if there is indeed a self-cycle, it should fail to compile anyway. *) let oc_deps (ast_file : string) (is_dev : bool) (db : Bsb_db_decode.t) (namespace : string option) (buf : Ext_buffer.t) (kind : [ `impl | `intf ]) @@ -133,9 +138,11 @@ let oc_deps (ast_file : string) (is_dev : bool) (db : Bsb_db_decode.t) while !offset < size do let next_tab = String.index_from s !offset magic_sep_char in let dependent_module = String.sub s !offset (next_tab - !offset) in - if dependent_module = cur_module_name then ( - prerr_endline ("FAILED: " ^ cur_module_name ^ " has a self cycle"); - exit 2); + if dependent_module = cur_module_name then + (*prerr_endline ("FAILED: " ^ cur_module_name ^ " has a self cycle"); + exit 2*) + (* #5368 ignore self dependencies *) () + else (match Bsb_db_decode.find db dependent_module is_dev with | None -> () | Some { dir_name; case } -> diff --git a/jscomp/build_tests/cycle/input.js b/jscomp/build_tests/cycle/input.js index bbe6620e7b..80b0e59806 100644 --- a/jscomp/build_tests/cycle/input.js +++ b/jscomp/build_tests/cycle/input.js @@ -1,7 +1,13 @@ //@ts-check -var cp = require("child_process"); -var assert = require("assert"); +const cp = require("child_process"); +const assert = require("assert"); +const fs = require('fs') +const path = require('path') var output = cp.spawnSync(`rescript`, { encoding: "utf8", shell: true }); assert(/dependency cycle/.test(output.stdout)); + +var compilerLogFile = path.join(__dirname, 'lib', 'bs', '.compiler.log'); +var compilerLog = fs.readFileSync(compilerLogFile, 'utf8'); +assert(/dependency cycle/.test(compilerLog)); \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/.gitignore b/jscomp/build_tests/cycle1/.gitignore new file mode 100644 index 0000000000..1c2bb277a5 --- /dev/null +++ b/jscomp/build_tests/cycle1/.gitignore @@ -0,0 +1,26 @@ +*.exe +*.obj +*.out +*.compile +*.native +*.byte +*.cmo +*.annot +*.cmi +*.cmx +*.cmt +*.cmti +*.cma +*.a +*.cmxa +*.obj +*~ +*.annot +*.cmj +*.bak +lib/bs +*.mlast +*.mliast +.vscode +.merlin +.bsb.lock \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/README.md b/jscomp/build_tests/cycle1/README.md new file mode 100644 index 0000000000..1c02d2a072 --- /dev/null +++ b/jscomp/build_tests/cycle1/README.md @@ -0,0 +1,16 @@ + + +# Build +``` +npm run build +``` + +# Watch + +``` +npm run watch +``` + + +# Editor +If you use `vscode`, Press `Windows + Shift + B` it will build automatically \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/bsconfig.json b/jscomp/build_tests/cycle1/bsconfig.json new file mode 100644 index 0000000000..2ab95ac677 --- /dev/null +++ b/jscomp/build_tests/cycle1/bsconfig.json @@ -0,0 +1,14 @@ +{ + "name": "cycle1", + "namespace": true, + "version": "0.1.0", + "sources": { + "dir" : "src", + "subdirs" : true + }, + "package-specs": { + "module": "es6", + "in-source": true + }, + "suffix": ".bs.js" +} diff --git a/jscomp/build_tests/cycle1/input.js b/jscomp/build_tests/cycle1/input.js new file mode 100644 index 0000000000..18694dcb5b --- /dev/null +++ b/jscomp/build_tests/cycle1/input.js @@ -0,0 +1,13 @@ +//@ts-check +const cp = require("child_process"); +const assert = require("assert"); +const fs = require('fs') +const path = require('path') + +var output = cp.spawnSync(`rescript`, { encoding: "utf8", shell: true }); + +assert(/is dangling/.test(output.stdout)); + +var compilerLogFile = path.join(__dirname, 'lib', 'bs', '.compiler.log'); +var compilerLog = fs.readFileSync(compilerLogFile, 'utf8'); +assert(/is dangling/.test(compilerLog)); \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/package.json b/jscomp/build_tests/cycle1/package.json new file mode 100644 index 0000000000..769afec06d --- /dev/null +++ b/jscomp/build_tests/cycle1/package.json @@ -0,0 +1,17 @@ +{ + "name": "cycle1", + "version": "0.1.0", + "scripts": { + "clean": "rescript clean", + "build": "rescript build", + "watch": "rescript build -w" + }, + "keywords": [ + "ReScript" + ], + "author": "", + "license": "MIT", + "devDependencies": { + "rescript": "^10.0.0" + } +} \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/src/A.res b/jscomp/build_tests/cycle1/src/A.res new file mode 100644 index 0000000000..237f168855 --- /dev/null +++ b/jscomp/build_tests/cycle1/src/A.res @@ -0,0 +1,3 @@ +include A + +let x = 42 \ No newline at end of file diff --git a/jscomp/build_tests/cycle1/src/A.resi b/jscomp/build_tests/cycle1/src/A.resi new file mode 100644 index 0000000000..86982fe068 --- /dev/null +++ b/jscomp/build_tests/cycle1/src/A.resi @@ -0,0 +1 @@ +let x : int \ No newline at end of file diff --git a/jscomp/build_tests/pinned/input.js b/jscomp/build_tests/pinned/input.js index 17d798fe87..5ee884ea44 100644 --- a/jscomp/build_tests/pinned/input.js +++ b/jscomp/build_tests/pinned/input.js @@ -9,6 +9,14 @@ function checkSpawnOut(out) { assert.fail(out.stderr + "\n" + out.stdout); } } + +// Clean beforehand to force its dependency to be rebuilt +var out = cp.spawnSync(`npx rescript clean`, { + encoding: "utf-8", + shell: true, +}); +checkSpawnOut(out); + var out = cp.spawnSync(`npx rescript build`, { encoding: "utf-8", shell: true, diff --git a/jscomp/build_tests/zerocycle/input.js b/jscomp/build_tests/zerocycle/input.js index 9bdb7007de..cd2db2e5b4 100644 --- a/jscomp/build_tests/zerocycle/input.js +++ b/jscomp/build_tests/zerocycle/input.js @@ -1,3 +1,4 @@ var p = require("child_process"); var assert = require("assert"); -p.spawnSync(`rescript`, { encoding: "utf8", cwd: __dirname }); +var out = p.spawnSync(`rescript`, { encoding: "utf8", cwd: __dirname }); +assert(out.status == 0) diff --git a/jscomp/build_tests/zerocycle/src/bar.res b/jscomp/build_tests/zerocycle/src/bar.res new file mode 100644 index 0000000000..1a8c37cbf2 --- /dev/null +++ b/jscomp/build_tests/zerocycle/src/bar.res @@ -0,0 +1,14 @@ +// one-file false positive: https://github.com/rescript-lang/rescript-compiler/issues/5368 + +module Nested = { + module Bar = { + type t = private int + } +} + +open Nested + +module Bar = { + open Bar + let t : t = Obj.magic(42) +} \ No newline at end of file diff --git a/jscomp/build_tests/zerocycle/src/demo2.res b/jscomp/build_tests/zerocycle/src/demo2.res new file mode 100644 index 0000000000..dc74456013 --- /dev/null +++ b/jscomp/build_tests/zerocycle/src/demo2.res @@ -0,0 +1 @@ +module Foo2 = {} \ No newline at end of file diff --git a/jscomp/build_tests/zerocycle/src/foo2.res b/jscomp/build_tests/zerocycle/src/foo2.res new file mode 100644 index 0000000000..24c75a3530 --- /dev/null +++ b/jscomp/build_tests/zerocycle/src/foo2.res @@ -0,0 +1,2 @@ +open Demo2 +include Foo2 \ No newline at end of file diff --git a/linux/ninja.exe b/linux/ninja.exe index 7fe9c14ddf..cae2d0155f 100755 Binary files a/linux/ninja.exe and b/linux/ninja.exe differ diff --git a/ninja b/ninja index 3a477ee7ca..b51c91cca7 160000 --- a/ninja +++ b/ninja @@ -1 +1 @@ -Subproject commit 3a477ee7cac769d25f0a8993612a7ea59411e48c +Subproject commit b51c91cca7a9d7ef3fff39585122ba20265753c6 diff --git a/win32/ninja.exe b/win32/ninja.exe index b978cd6e27..9fb9975786 100644 Binary files a/win32/ninja.exe and b/win32/ninja.exe differ