{"record":{"id":"7d168dd2395a6308","repo":"karatelabs/karate","slug":"constructor-map-requires-new","errorCode":null,"errorMessage":"Constructor Map requires 'new'","messagePattern":"Constructor Map requires 'new'","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsMapConstructor.java","lineNumber":62,"sourceCode":"        defineOwn(\"prototype\", JsMapPrototype.INSTANCE, PropertySlot.INTRINSIC);\n        defineOwn(\"groupBy\", new JsBuiltinMethod(\"groupBy\", 2, (JsCallable) this::groupBy), METHOD_ATTRS);\n    }\n\n    private Object groupBy(Context context, Object[] args) {\n        Object items = args.length > 0 ? args[0] : Terms.UNDEFINED;\n        Object callback = args.length > 1 ? args[1] : Terms.UNDEFINED;\n        // Spec: result is a fresh Map; keys carry -0 → +0 normalization (zero\n        // coercion mode) — verified by negativeZero.js.\n        return GroupByImpl.toMap(\n                GroupByImpl.run(items, callback, /* propertyMode= */ false, context));\n    }\n\n    @Override\n    public Object call(Context context, Object[] args) {\n        CallInfo callInfo = context.getCallInfo();\n        boolean isNew = callInfo != null && callInfo.constructor;\n        if (!isNew) {\n            throw JsErrorException.typeError(\"Constructor Map requires 'new'\");\n        }\n        JsMap map = new JsMap();\n        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {\n            return map;\n        }\n        // Look up `set` on the freshly-constructed map's prototype chain — honors\n        // user-overridden Map.prototype.set per spec 24.1.1.1 step 9.\n        Object setFn = map.getMember(\"set\");\n        if (!(setFn instanceof JsCallable adder)) {\n            throw JsErrorException.typeError(\"Map.prototype.set is not callable\");\n        }\n        JsIterator iter = IterUtils.getIterator(args[0], context);\n        CoreContext cc = context instanceof CoreContext c ? c : null;\n        Object savedThis = cc != null ? cc.thisObject : null;\n        try {\n            while (iter.hasNext()) {\n                Object entry = iter.next();\n                if (!(entry instanceof List) && !(entry instanceof ObjectLike)) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsMapConstructor.java#L44-L80","documentation":"The Map constructor was invoked without `new` (e.g. `Map()` instead of `new Map()`). Karate's JS engine checks callInfo.constructor in JsMapConstructor.call and throws a TypeError because built-in constructors like Map cannot be called as plain functions (unlike, say, Object or Array).","triggerScenarios":"Calling Map() directly; passing Map as a callback where `new` semantics are lost (e.g. arr.map(Map)); refactors that dropped the `new` keyword; calling it through a wrapper that invokes without constructor context.","commonSituations":"Porting code patterns where new was optional for other constructors; default-parameter fallbacks like `options.map || Map()`; transpiled/minified code that stripped `new`.","solutions":["Add the `new` keyword: `new Map()`.","If you need call-or-construct flexibility, write `var m = x instanceof Map ? x : new Map(...)`.","Ensure callbacks/wrappers that create maps use Reflect-style construction or an explicit arrow returning `new Map(...)`.","Audit for other built-ins (WeakMap, Set) that share the same requirement."],"exampleFix":"// before\nvar m = Map(entries); // TypeError\n// after\nvar m = new Map(entries);","handlingStrategy":"type-guard","validationCode":"if (typeof Map !== 'function') throw new Error('Map unavailable'); // construction sites must use new","typeGuard":"function isMap(v) { return v instanceof Map; }","tryCatchPattern":"try { var m = makeMap(entries); } catch (e) { if (String(e).indexOf(\"requires 'new'\") !== -1) { var m2 = new Map(entries); } else { throw e; } }","preventionTips":["Always invoke built-in constructors (Map, Set, WeakMap) with new","Never pass the constructor itself as a plain callback","Wrap construction in helper functions that enforce new internally"],"tags":["javascript","typeerror","map","constructor"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}