let testArr = [
    ["USA", "Mexico"],
    ["Green", "Red", "Blue"],
    ["Metall", "Glass", "Plastic"],
];

function arrayOfTree(arr = []) {
    let iter = arr.reduce((a, b) => a * b.length, 1); // 18
    let res = Array.from(Array(iter), () => Array(arr.length)); // 18*3

    let step = iter;
    let i = 0;

    for (let k = 0; k < arr.length; k++) {
        step = step / arr[k].length; // 9, 3, 1
        // console.log("step - ", step);
        i = 0;
        for (let j = 0; j < iter; j++) {
            res[j][k] = arr[k][Math.floor(i++ / step) % arr[k].length];
        }
    }

    return res;
}

console.log(arrayOfTree(testArr));

// не боится пустого массива на входе

//////////////////
//////////////////
//////////////////
//////////////////
//////////////////
//////////////////

var list = [
    ["USA", "Mexico"],
    ["Green", "Red", "Blue"],
    ["Metall", "Glass", "Plastic"],
];
var tree = [];

list.forEach(function (listArrayValue, listKey) {
    let secondListKeyElement = 1;
    if (listKey === 0) {
        addElementsToSecondBranch(list, tree, secondListKeyElement, listArrayValue);
    }
});

function addElementsToSecondBranch(list, tree, secondListKeyElement, listArrayValue) {
    listArrayValue.forEach(function (branchKey) {
        tree[branchKey] = [];
        if (typeof tree[branchKey] !== "undefined" && typeof list[secondListKeyElement] !== "undefined") {
            addElementsToSecondBranch(list, tree[branchKey], secondListKeyElement + 1, list[secondListKeyElement]);
        }
    });
}

console.log(tree);

/////////////
/////////////
/////////////
/////////////
/////////////
/////////////
/////////////
/////////////

let testArr = [
    ["USA", "Mexico"],
    ["Green", "Red", "Blue"],
    ["Metall", "Glass", "Plastic"],
];

(() => {
    const inc = (indexes) => {
        let i;
        for (i = testArr.length - 1; i >= 0 && testArr[i].length <= (indexes[i] || 0) + 1; i--);
        if (i === -1) return NaN;
        indexes[i] = (indexes[i] || 0) + 1;
        i < testArr.length - 1 && (indexes[i + 1] = 0);
        return [...indexes];
    };

    let indexes = [0, 0, 0],
        result = [];

    do {
        result.push(indexes.map((i, j) => testArr[j][i || 0]));
    } while ((indexes = inc(indexes)));
    return result;
})();
