From 17406c6b810885bbc3ed3a82e1600635bd8601a3 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:51:03 +0200 Subject: [PATCH] feat: create build process for environment --- .gitignore | 18 +- build.gradle | 33 ++ gradle/wrapper/gradle-wrapper.properties | 7 - package.json | 24 + rollup.config.js | 125 ++++++ src/compiler/main.ts | 235 ---------- src/main/resources/lib/index.js | 542 ----------------------- 7 files changed, 187 insertions(+), 797 deletions(-) delete mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 package.json create mode 100644 rollup.config.js delete mode 100644 src/compiler/main.ts delete mode 100644 src/main/resources/lib/index.js diff --git a/.gitignore b/.gitignore index edf93b9..93740a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,18 @@ -* - -!/src/ -!/src/**/* +/* +!/src !/doc -!/doc/**/* - !/tests -!/tests/**/* - !/.github -!/.github/**/* !/.gitignore !/.gitattributes !/LICENSE !/README.md + !/settings.gradle !/build.gradle !/gradle.properties -!/gradle -!/gradle/wrapper -!/gradle/wrapper/gradle-wrapper.properties -!/ \ No newline at end of file +!/package.json +!/rollup.config.js diff --git a/build.gradle b/build.gradle index 18a1e3e..a37bb4b 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ import java.text.SimpleDateFormat plugins { id 'application' + id 'com.github.node-gradle.node' version '5.0.0' id 'net.nemerosa.versioning' version '2.15.0' id 'org.ajoberstar.grgit' version '5.0.0-rc.3' // required by gradle @@ -14,6 +15,31 @@ version = project.project_version group = project.project_group description = 'ES5-compliant JavaScript interpreter' +node { + version = '20.0.0' + npmVersion = '8.0.0' + download = true +} + +task compileEnv(type: NpmTask) { + inputs.files('rollup.config.js') + inputs.dir('src/lib/libs') + outputs.files("build/js/env.js") + + // group = 'build' + args = ['run', 'build-env'] +} +task compileTypescript(type: NpmTask) { + inputs.files('rollup.config.js') + inputs.dir('src/lib/ts') + outputs.files("build/js/ts.js") + environment.put("NODE_OPTIONS", "--max-old-space-size=4096") + + // group = 'build' + args = ['run', 'build-ts'] +} + + repositories { mavenCentral() } @@ -73,6 +99,13 @@ distTar { } processResources { + dependsOn compileEnv + dependsOn compileTypescript + + from("build/js") { + into "lib" + } + filesMatching "metadata.json", { expand( version: project.project_version, diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9355b41..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/package.json b/package.json new file mode 100644 index 0000000..e8c346d --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "scripts": { + "build-env": "rollup -c --environment INPUT:src/lib/libs/_entry.ts,OUTPUT:build/js/index.js,POLYFILLS:src/lib/libs/polyfills", + "build-ts": "rollup -c --environment INPUT:src/lib/ts/_entry.ts,OUTPUT:build/js/ts.js" + }, + "dependencies": { + "@babel/runtime": "^7.26.0", + "typescript": "^5.7.2" + }, + "devDependencies": { + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9", + "@babel/preset-env": "^7.26.0", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.1", + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.1", + "@types/node": "^22.10.1", + "rollup": "^4.24.0", + "tslib": "^2.8.0" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..b4a7021 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,125 @@ +const { defineConfig } = require("rollup"); +const terser = require("@rollup/plugin-terser"); +const typescript = require("@rollup/plugin-typescript"); +const babel = require("@rollup/plugin-babel"); +const commonjs = require("@rollup/plugin-commonjs"); +const nodeResolve = require("@rollup/plugin-node-resolve"); +const { resolve } = require("path"); + +const shouldMinify = () => false; +const shouldEmitSourcemaps = () => true; +const shouldPolyfill = () => !!process.env.POLYFILLS; + +const construct = (input, output) => defineConfig({ + input, + plugins: [ + shouldPolyfill() && { + name: "babel-fake-runtime", + resolveId(source) { + if (source.startsWith("!polyfills:/helpers")) return resolve(process.env.POLYFILLS) + source.slice(19) + ".js"; + } + }, + commonjs(), + nodeResolve(), + babel({ + extensions: [], + exclude: ["node_modules/**"], + + babelHelpers: "runtime", + plugins: [ + ["@babel/plugin-transform-typescript", { + onlyRemoveTypeImports: true, + optimizeConstEnums: true, + allowDeclareFields: true, + }], + ["@babel/plugin-transform-class-properties"], + ["@babel/plugin-transform-runtime", { + moduleName: shouldPolyfill() ? "!polyfills:" : undefined, + version: "^7.24.0", + }], + ] + }), + babel({ + extensions: [], + exclude: shouldPolyfill() ? [process.env.POLYFILLS + "/**"] : [], + + assumptions: { + ignoreToPrimitiveHint: true, + noClassCalls: true, + }, + + env: { + development: { compact: false }, + }, + + babelHelpers: "runtime", + plugins: [ + "@babel/plugin-transform-arrow-functions", + "@babel/plugin-transform-block-scoping", + "@babel/plugin-transform-classes", + "@babel/plugin-transform-computed-properties", + "@babel/plugin-transform-destructuring", + "@babel/plugin-transform-for-of", + "@babel/plugin-transform-object-super", + "@babel/plugin-transform-parameters", + "@babel/plugin-transform-shorthand-properties", + "@babel/plugin-transform-spread", + "@babel/plugin-transform-object-rest-spread", + "@babel/plugin-transform-template-literals", + "@babel/plugin-transform-unicode-escapes", + "@babel/plugin-transform-unicode-regex", + "@babel/plugin-transform-exponentiation-operator", + "@babel/plugin-transform-async-to-generator", + "@babel/plugin-transform-async-generator-functions", + "@babel/plugin-transform-nullish-coalescing-operator", + "@babel/plugin-transform-optional-chaining", + "@babel/plugin-transform-logical-assignment-operators", + "@babel/plugin-transform-numeric-separator", + "@babel/plugin-transform-class-properties", + "@babel/plugin-transform-class-static-block", + "@babel/plugin-transform-regenerator", + + ["@babel/plugin-transform-runtime", { + moduleName: shouldPolyfill() ? "!polyfills:" : undefined, + version: "^7.24.0", + }], + ], + }), + typescript({ + exclude: ["node_modules/**", "*.js"], + compilerOptions: { + allowImportingTsExtensions: true, + noEmit: true, + }, + noForceEmit: true, + noEmitOnError: true, + }), + shouldMinify() && terser({ + sourceMap: shouldEmitSourcemaps(), + keep_classnames: true, + }), + { + load(source) { + console.log(source); + } + }, + ], + output: { + file: output, + format: "iife", + globals: { + fs: "null", + path: "null", + os: "null", + inspector: "null", + }, + // plugins: [babel.getBabelOutputPlugin({ + // allowAllFormats: true, + // })], + + sourcemap: shouldEmitSourcemaps(), + inlineDynamicImports: true, + }, +}); + +module.exports = construct(process.env.INPUT, process.env.OUTPUT); diff --git a/src/compiler/main.ts b/src/compiler/main.ts deleted file mode 100644 index a4063b3..0000000 --- a/src/compiler/main.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { parse } from "acorn"; -import {} from "acorn"; -import { traverse } from "estraverse"; -import { Declaration, Identifier, Node, VariableDeclaration } from "estree"; - -enum VariableType { - Var, - Let, - Const, -} - -class Variable { - public constructor( - public readonly scope: Scope, - public readonly name: string, - public readonly type: VariableType, - public readonly readers = new Set(), - public readonly writers = new Set(), - ) { } - - public child(scope: Scope) { - return new Variable(scope, this.name, this.type, this.readers, this.writers); - } - - public get writable() { - return this.type !== VariableType.Const; - } -} - -class Scope { - private _locals = new Set(); - private _capturables = new Set(); - private _captures = new Set(); - - private _localNames = new Map(); - private _captureNames = new Map(); - private _parentToChild = new Map(); - private _childToParent = new Map(); - - public get locals() { - return Iterator.from(this._locals.values()); - } - - private _addCapture(v?: Variable) { - if (v != null && this._locals.delete(v)) { - this._capturables.add(v); - } - - return v; - } - - public capture(name: string) { - if (this._localNames.has(name)) return this._addCapture(this._localNames.get(name)); - if (this._captureNames.has(name)) return this._addCapture(this._captureNames.get(name)); - - const parent = this.parent?.capture(name); - if (parent == null) return undefined; - - const child = parent.child(this); - - this._parentToChild.set(parent, child); - this._childToParent.set(child, parent); - this._captures.add(child); - this._captureNames.set(child.name, child); - } - - public add(name: string, type: VariableType) { - let res = this.get(name, false); - if (res != null) return res; - - res = new Variable(this, name, type); - this._locals.add(res); - this._localNames.set(name, res); - return res; - } - public get(name: string, capture = true): Variable | undefined { - if (this._localNames.has(name)) return this._localNames.get(name); - if (this._captureNames.has(name)) return this._captureNames.get(name); - - if (capture) this.parent?.capture(name); - else return undefined; - } - - public constructor( - public readonly major: boolean, - public readonly node: Node, - public readonly parent?: Scope, - ) { } -} - -class BiMap implements Iterable<[A, B]> { - private _first = new Map(); - private _second = new Map(); - - public get(val: A): B; - public get(val: B): A; - public get(val: any) { - if (this._first.has(val)) return this._first.get(val); - if (this._second.has(val)) return this._second.get(val); - if (this._same.has(val)) return val; - return undefined; - } - - public set(a: A, b: B) { - this._first.set(a, b); - this._second.set(b, a); - - return this; - } - - public has(val: A | B) { - return this._first.has(val as any) || this._second.has(val as any); - } - - public delete(val: A | B) { - if (this._first.has(val as any)) { - const second = this._first.get(val as any)!; - this._first.delete(val as any); - this._second.delete(second); - - return true; - } - else if (this._second.has(val as any)) { - const first = this._second.get(val as any)!; - this._second.delete(val as any); - this._first.delete(first); - - return true; - } - else return false; - } - - public *[Symbol.iterator]() { - yield *this._first; - } - public *keys() { - yield *this._first.keys(); - } - public *values() { - yield *this._second.keys(); - } - public *entries() { - yield *this._first.entries(); - } -} - -class ResolutionContext { - public readonly variableRefs = new Map(); - public readonly declarations = new BiMap(); - - public resolveVariables() { - for (const el of this.variableRefs) { - } - } -} - -class NodeContext { - public node: Node = undefined!; - public path: Node[] = []; - - public atPath(i: number) { - return this.path[this.path.length - 1 - i]; - } - - public scope: Scope = undefined!; - public declType?: VariableType; -} - -interface Collector { - enter(ctx: NodeContext, root: ResolutionContext): void; - leave(ctx: NodeContext, root: ResolutionContext): void; -} - -function collect(node: Node, root: ResolutionContext, ...collectors: Collector[]) { - const nodeCtx = new NodeContext(); - const path: Node[] = []; - - traverse(node, { - enter(node) { - nodeCtx.node = node; - nodeCtx.path.push(node); - for (let i = 0; i < collectors.length; i++) { - collectors[i].enter(nodeCtx, root); - } - }, - leave(node) { - nodeCtx.node = node; - nodeCtx.path.pop(); - for (let i = 0; i < collectors.length; i++) { - collectors[i].leave(nodeCtx, root); - } - }, - }); -} - -function assertDefined(val: unknown): asserts val is {} { - if (val == null) throw new Error("Undefined or null expression"); -} - -const scopeCollector: Collector = { - enter(ctx, root) { - if (ctx.node.type === "BlockStatement") { - ctx.scope = new Scope(false, ctx.node, ctx.scope.parent); - } - else if (ctx.node.type === "VariableDeclaration") { - switch (ctx.node.kind) { - case "var": ctx.declType = VariableType.Var; break; - case "let": ctx.declType = VariableType.Let; break; - case "const": ctx.declType = VariableType.Const; break; - default: throw new Error(`Unknown variable type '${(ctx.node as any).kind}'`); - } - } - else if (ctx.node.type === "VariableDeclarator") { - ctx.scope. - } - else if (ctx.node.type === "ClassDeclaration") { - - } - else if (ctx.node.type === "Identifier") { - } - }, - leave(ctx, root) { - if (ctx.scope.node === ctx.node) { - assertDefined(ctx.scope.parent); - ctx.scope = ctx.scope.parent; - } - else if (ctx.node.type === "VariableDeclaration") { - ctx.declType = undefined; - } - }, -}; - - -const program = parse("const a = 10;", { ecmaVersion: "latest" }) as Node; -collect(program, domain, ...stage1); \ No newline at end of file diff --git a/src/main/resources/lib/index.js b/src/main/resources/lib/index.js deleted file mode 100644 index 4fce58e..0000000 --- a/src/main/resources/lib/index.js +++ /dev/null @@ -1,542 +0,0 @@ -(function main() { - var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - }; - - function extend(derived, base) { - if (base == null) { - object.setPrototype(derived.prototype, null); - } - else { - object.setPrototype(derived, base); - object.setPrototype(derived.prototype, base.prototype); - } - } - - var target = arguments[0]; - var primordials = arguments[1]; - var symbol = primordials.symbol || (function () { - var repo = {}; - return { - makeSymbol: function (name) { return { name: name }; }, - getSymbol: function (name) { - if (name in repo) return repo[name]; - else return repo[name] = { name: name }; - }, - getSymbolKey: function (symbol) { - if (symbol.name in repo && repo[symbol.name] === symbol) return symbol.name; - else return undefined; - }, - getSymbolDescription: function (symbol) { - return symbol.name; - } - }; - }); - var number = primordials.number || { - parseInt: function () { throw new Error("parseInt not supported"); }, - parseFloat: function () { throw new Error("parseFloat not supported"); }, - isNaN: function (val) { return val !== val; }, - NaN: 0 / 0, - Infinity: 1 / 0, - }; - var string = primordials.string; - var object = primordials.object || { - defineProperty: function () { throw new Error("Define property not polyfillable"); }, - defineField: function (obj, key, a, b, c, value) { obj[key] = value; }, - getOwnMember: function () { throw new Error("Get own member not polyfillable"); }, - getOwnSymbolMember: function () { throw new Error("Get own symbol member not polyfillable"); }, - getOwnMembers: function () { throw new Error("Get own members not polyfillable"); }, - getOwnSymbolMembers: function () { throw new Error("Get own symbol members not polyfillable"); }, - getPrototype: function () { throw new Error("Get prototype not polyfillable"); }, - setPrototype: function () { throw new Error("Set prototype not polyfillable"); }, - }; - var func = primordials.function || { - invokeType: function (args, self) { - if (typeof self === "object") return "new"; - else return "call"; - }, - setConstructable: function () { throw new Error("Set constructable not polyfillable"); }, - setCallable: function () { throw new Error("Set callable not polyfillable"); }, - invoke: function () { throw new Error("Invoke not polyfillable"); }, - construct: function () { throw new Error("Construct not polyfillable"); }, - }; - var json = primordials.json || { - stringify: function (val) { throw new Error("JSON stringify not polyfillable"); }, - parse: function (val) { throw new Error("JSON parse not polyfillable"); }, - }; - var map = primordials.map; - var regex = primordials.regex; - - var setGlobalPrototypes = primordials.setGlobalPrototypes; - var compile = primordials.compile; - var valueKey = symbol.makeSymbol("Primitive.value"); - var undefined = void 0; - target.undefined = undefined; - - function unwrapThis(self, type, constr, name, arg, defaultVal) { - if (arg === void 0) { arg = "this"; } - if (typeof self === type) - return self; - if (self instanceof constr && valueKey in self) - self = self[valueKey]; - if (typeof self === type) - return self; - if (defaultVal !== undefined) - return defaultVal; - throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name); - } - function wrapIndex(i, len) { } - function Symbol(name) { - if (name === undefined) name = ""; - return symbol.makeSymbol(name); - } - Symbol.prototype.toString = function () { - return "Symbol(" + unwrapThis(this, "symbol", Symbol, "Symbol.prototype.toString").description + ")"; - }; - Symbol.prototype.valueOf = function () { - return unwrapThis(this, "symbol", Symbol, "Symbol.prototype.valueOf"); - }; - Symbol.for = function (name) { - return symbol.getSymbol(name + ""); - }; - Symbol.keyFor = function (value) { - return symbol.getSymbolKey(unwrapThis(value, "symbol", Symbol, "Symbol.keyFor")); - }; - object.defineProperty(Symbol.prototype, "desc", false, true, function () { - return symbol.getSymbolDescriptor(unwrapThis(this, "symbol", Symbol, "Symbol.prototype.description")); - }); - object.defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator")); - object.defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator")); - object.defineField(Symbol, "match", false, false, false, Symbol("Symbol.match")); - object.defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll")); - object.defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace")); - object.defineField(Symbol, "search", false, false, false, Symbol("Symbol.search")); - object.defineField(Symbol, "split", false, false, false, Symbol("Symbol.split")); - object.defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag")); - func.setConstructable(Symbol, false); - target.Symbol = Symbol; - - function Number(value) { - if (func.invokeType(arguments, this) === "call") { - if (arguments.length === 0) return 0; - else return +value; - } - this[valueKey] = target.Number(value); - } - Number.prototype.toString = function () { - return "" + unwrapThis(this, "number", Number, "Number.prototype.toString"); - }; - Number.prototype.valueOf = function () { - return unwrapThis(this, "number", Number, "Number.prototype.toString"); - }; - Number.isFinite = function (value) { - value = unwrapThis(value, "number", Number, "Number.isFinite", "value", undefined); - if (value === undefined || value !== value) - return false; - if (value === Infinity || value === -Infinity) - return false; - return true; - }; - Number.isInteger = function (value) { - value = unwrapThis(value, "number", Number, "Number.isInteger", "value", undefined); - if (value === undefined) - return false; - return number.parseInt(value) === value; - }; - Number.isNaN = function (value) { - return number.isNaN(value); - }; - Number.isSafeInteger = function (value) { - value = unwrapThis(value, "number", Number, "Number.isSafeInteger", "value", undefined); - if (value === undefined || number.parseInt(value) !== value) - return false; - return value >= -9007199254740991 && value <= 9007199254740991; - }; - Number.parseFloat = function (value) { - value = 0 + value; - return number.parseFloat(value); - }; - Number.parseInt = function (value, radix) { - value = 0 + value; - radix = +radix; - if (number.isNaN(radix)) - radix = 10; - return number.parseInt(value, radix); - }; - - object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); - object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); - object.defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991); - object.defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity); - object.defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity); - object.defineField(Number, "NaN", false, false, false, number.NaN); - object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); - object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324); - func.setCallable(Number, true); - target.Number = Number; - target.parseInt = Number.parseInt; - target.parseFloat = Number.parseFloat; - target.NaN = Number.NaN; - target.Infinity = Number.POSITIVE_INFINITY; - - function String(value) { - if (func.invokeType(arguments, this) === "call") { - if (arguments.length === 0) - return ""; - else - return value + ""; - } - this[valueKey] = String(value); - } - String.prototype.at = function (index) { - throw "Not implemented :/"; - return unwrapThis(this, "string", String, "String.prototype.at")[index]; - }; - String.prototype.toString = function () { - return unwrapThis(this, "string", String, "String.prototype.toString"); - }; - String.prototype.valueOf = function () { - return unwrapThis(this, "string", String, "String.prototype.valueOf"); - }; - String.prototype[Symbol.iterator] = function () { - var i = 0; - var arr = this; - - var obj = { - next: function () { - if (arr == null) return { done: true, value: undefined }; - if (i > arr.length) { - arr = undefined; - return { done: true, value: undefined }; - } - else { - var val = arr[i++]; - if (i >= arr.length) arr = undefined; - return { done: false, value: val }; - } - } - }; - obj[Symbol.iterator] = function () { return this; }; - return obj; - } - String.fromCharCode = function () { - var res = []; - res[arguments.length] = 0; - for (var i = 0; i < arguments.length; i++) { - res[i] = string.fromCharCode(+arguments[i]); - } - return string.stringBuild(res); - }; - String.fromCodePoint = function () { - var res = []; - res[arguments.length] = 0; - - for (var i = 0; i < arguments.length; i++) { - res[i] = string.fromCodePoint(+arguments[i]); - } - return string.stringBuild(res); - }; - func.setCallable(String, true); - target.String = String; - - function Boolean(value) { - if (func.invokeType(arguments, this) === "call") { - if (arguments.length === 0) return false; - else return !!value; - } - this[valueKey] = Boolean(value); - } - Boolean.prototype.toString = function () { - return "" + unwrapThis(this, "boolean", Boolean, "Boolean.prototype.toString"); - }; - Boolean.prototype.valueOf = function () { - return unwrapThis(this, "boolean", Boolean, "Boolean.prototype.valueOf"); - }; - func.setCallable(Boolean, true); - target.Boolean = Boolean; - - function Object(value) { - if (typeof value === 'object' && value !== null) return value; - if (typeof value === 'string') return new String(value); - if (typeof value === 'number') return new Number(value); - if (typeof value === 'boolean') return new Boolean(value); - if (typeof value === 'symbol') { - var res = {}; - setPrototype(res, Symbol.prototype); - res[valueKey] = value; - return res; - } - - return {}; - // // TODO: use new.target.prototype as proto - // if (target == null || typeof target !== 'object') target = {}; - // return target; - } - Object.prototype.toString = function () { - if (this !== null && this !== undefined && (Symbol.toStringTag in this)) return "[object " + this[Symbol.toStringTag] + "]"; - else if (typeof this === "number" || this instanceof Number) return "[object Number]"; - else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]"; - else if (typeof this === "string" || this instanceof String) return "[object String]"; - else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]"; - else if (typeof this === "function") return "[object Function]"; - else return "[object Object]"; - }; - Object.prototype.valueOf = function () { - return this; - }; - Object.defineProperty = function (obj, key, desc) { - if (typeof obj !== "object" || obj === null) throw new TypeError("Object.defineProperty called on non-object"); - if (typeof desc !== "object" || desc === null) throw new TypeError("Property description must be an object: " + desc); - if ("get" in desc || "set" in desc) { - var get = desc.get, set = desc.set; - - if (get !== undefined && typeof get !== "function") throw new TypeError("Getter must be a function: " + get); - if (set !== undefined && typeof set !== "function") throw new TypeError("Setter must be a function: " + set); - if ("value" in desc || "writable" in desc) { - throw new TypeError("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute"); - } - if (!object.defineProperty(obj, key, desc.enumerable, desc.configurable, get, set)) { - throw new TypeError("Cannot redefine property: " + key); - } - } - else if (!object.defineField(obj, key, desc.writable, desc.enumerable, desc.configurable, desc.value)) { - throw new TypeError("Cannot redefine property: " + key); - } - - return obj; - }; - func.setCallable(Object, true); - extend(Object, null); - object.setPrototype(Object.prototype, null); - target.Object = Object; - - function Function() { - var parts = ["(function annonymous("]; - for (var i = 0; i < arguments.length - 1; i++) { - if (i > 0) - parts[parts.length] = ","; - parts[parts.length] = arguments[i]; - } - parts[parts.length] = "){\n"; - parts[parts.length] = String(arguments[arguments.length - 1]); - parts[parts.length] = "\n})"; - var res = compile(string.stringBuild(parts))(); - return res; - } - Function.prototype.toString = function () { - if (this.name !== "") - return "function " + this.name + "(...) { ... }"; - else - return "function (...) { ... }"; - }; - Function.compile = function (src, opts) { - if (src === void 0) src = ""; - if (opts === void 0) opts = {}; - if (opts.globals === void 0) opts.globals = []; - if (opts.wrap === void 0) opts.wrap = false; - - var globals = opts.globals; - var wrap = opts.wrap; - var parts = []; - - if (wrap) parts[parts.length] = "return (function() {\n"; - if (globals.length > 0) { - parts[parts.length] = "let {"; - for (var i = 0; i < globals.length; i++) { - if (i > 0) parts[parts.length] = ","; - parts[parts.length] = globals[i]; - } - parts[parts.length] = "} = arguments[0];"; - } - parts[parts.length] = src; - if (wrap) parts[parts.length] = "\n})(arguments[0])"; - - var res = compile(string.stringBuild(parts)); - return res; - }; - func.setCallable(Function, true); - target.Function = Function; - - function Array(len) { - if (arguments.length === 1 && typeof len === "number") { - var res = []; - res.length = len; - return res; - } - // TODO: Implement spreading - else throw new Error("Spreading not implemented"); - } - Array.prototype[Symbol.iterator] = function () { - var i = 0; - var arr = this; - - var obj = { - next: function () { - if (arr == null) return { done: true, value: undefined }; - if (i > arr.length) { - arr = undefined; - return { done: true, value: undefined }; - } - else { - var val = arr[i++]; - if (i >= arr.length) arr = undefined; - return { done: false, value: val }; - } - } - }; - obj[Symbol.iterator] = function () { return this; }; - return obj; - } - Array.isArray = function (val) { - return val instanceof Array; - } - func.setCallable(Array, true); - target.Array = Array; - - function Error(msg) { - if (msg === void 0) { msg = ""; } - if (func.invokeType(arguments, this) === "call") - return new Error(msg); - this.message = msg + ""; - } - Error.prototype.toString = function () { - var res = this.name || "Error"; - var msg = this.message; - if (msg) - res += ": " + msg; - return res; - }; - object.defineField(Error.prototype, "name", true, false, true, "Error"); - object.defineField(Error.prototype, "message", true, false, true, ""); - func.setCallable(Error, true); - target.Error = Error; - - extend(SyntaxError, Error); - function SyntaxError(msg) { - if (func.invokeType(arguments, this) === "call") - return new SyntaxError(msg); - return _super.call(this, msg) || this; - } - object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError"); - func.setCallable(SyntaxError, true); - target.SyntaxError = SyntaxError; - - extend(TypeError, Error); - function TypeError(msg) { - if (func.invokeType(arguments, this) === "call") - return new TypeError(msg); - return _super.call(this, msg) || this; - } - object.defineField(TypeError.prototype, "name", true, false, true, "TypeError"); - func.setCallable(TypeError, true); - target.TypeError = TypeError; - - extend(RangeError, Error); - function RangeError(msg) { - if (func.invokeType(arguments, this) === "call") - return new RangeError(msg); - return _super.call(this, msg) || this; - } - object.defineField(RangeError.prototype, "name", true, false, true, "RangeError"); - func.setCallable(RangeError, true); - target.RangeError = RangeError; - - target.uint8 = primordials.uint8; - - var mapKey = Symbol("Map.impl"); - - function Map(iterable) { - var _map = this[mapKey] = new map(); - - if (iterable != null) { - var it = iterable[Symbol.iterator](); - for (var val = it.next(); !val.done; val = it.next()) { - _map.set(val.value[0], val.value[1]); - } - } - } - - Map.prototype.get = function (key) { - return this[mapKey].get(key); - } - Map.prototype.has = function (key) { - return this[mapKey].has(key); - } - Map.prototype.set = function (key, val) { - return this[mapKey].set(key, val); - } - Map.prototype.delete = function (key, val) { - return this[mapKey].delete(key, val); - } - Map.prototype.keys = function (key, val) { - return this[mapKey].keys(key, val); - } - Map.prototype.values = function (key, val) { - var res = this[mapKey].keys(key, val); - for (var i = 0; i < res.length; i++) res[i] = this[mapKey].get(res[i]); - return res; - } - Map.prototype.entries = function (key, val) { - var res = this[mapKey].keys(key, val); - for (var i = 0; i < res.length; i++) res[i] = [res[i], this[mapKey].get(res[i])]; - return res; - } - - func.setCallable(Map, false); - target.Map = Map; - - var regexKey = Symbol("RegExp.impl"); - - function RegExp(source, flags) { - var _regex = this[regexKey] = new regex(); - - source = this.source = String("source" in source ? source.source : source); - flags = String(flags); - - var indices = false, global = false, ignoreCase = false, multiline = false, dotall = false, unicode = false, unicodeSets = false, sticky = false; - - for (var i = 0; i < flags.length; i++) { - switch (flags[i]) { - case "d": indices = true; break; - case "g": global = true; break; - case "i": ignoreCase = true; break; - case "m": multiline = true; break; - case "s": dotall = true; break; - case "u": unicode = true; break; - case "v": unicodeSets = true; break; - case "y": sticky = true; break; - } - } - - flags = ""; - if (indices) flags += "d"; - if (global) flags += "g"; - if (ignoreCase) flags += "i"; - if (multiline) flags += "m"; - if (dotall) flags += "s"; - if (unicode) flags += "u"; - if (unicodeSets) flags += "v"; - if (sticky) flags += "y"; - this.flags = flags; - - - } - - target.RegExp = RegExp; - - - setGlobalPrototypes({ - string: String.prototype, - number: Number.prototype, - boolean: Boolean.prototype, - symbol: Symbol.prototype, - object: Object.prototype, - array: Array.prototype, - function: Function.prototype, - error: Error.prototype, - syntax: SyntaxError.prototype, - range: RangeError.prototype, - type: TypeError.prototype, - regex: RegExp, - }); -})(arguments[0], arguments[1]);