Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

core-decorators

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

core-decorators - npm Package Compare versions

Comparing version 0.0.1-broken to 0.0.1

212

index.js

@@ -0,25 +1,95 @@

const GENERIC_FUNCTION_ERROR = '{child} does not properly override {parent}';
const FUNCTION_REGEXP = /^function ([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?(\([^\)]*\))[\s\S]+$/;
class SyntaxErrorReporter {
key: string;
parent: Function;
child: Function;
// undefined values needed until this babel PR is released:
// https://github.com/babel/babel/pull/1256
parentKlass = undefined;
childKlass = undefined;
parentDescriptor = undefined;
childDescriptor = undefined;
get key() {
return this.childDescriptor.key;
}
get parentNotation() {
return `${this.parent.constructor.name}#${this.key}`;
return `${this.parentKlass.constructor.name}#${this.parentPropertySignature}`;
}
get childNotation() {
return `${this.child.constructor.name}#${this.key}`;
return `${this.childKlass.constructor.name}#${this.childPropertySignature}`;
}
get parentTopic() {
return this._getTopic(this.parentDescriptor);
}
get childTopic() {
return this._getTopic(this.childDescriptor);
}
_getTopic(descriptor) {
if (descriptor === undefined) {
return null;
}
if ('value' in descriptor) {
return descriptor.value;
}
if ('get' in descriptor) {
return descriptor.get;
}
if ('set' in descriptor) {
return descriptor.set;
}
}
get parentPropertySignature() {
return this._extractTopicSignature(this.parentTopic);
}
get childPropertySignature() {
return this._extractTopicSignature(this.childTopic);
}
_extractTopicSignature(topic) {
switch (typeof topic) {
case 'function':
return this._extractFunctionSignature(topic);
default:
return this.key;
}
}
_extractFunctionSignature(fn) {
return fn
.toString()
.replace(
FUNCTION_REGEXP,
(match, name = this.key, params) => name + params
);
}
constructor(propertyKey, parentKlass, childClass) {
this.key = propertyKey;
this.parent = parentKlass;
this.child = childClass;
constructor(parentKlass, childKlass, parentDescriptor, childDescriptor) {
this.parentKlass = parentKlass;
this.childKlass = childKlass;
this.parentDescriptor = parentDescriptor;
this.childDescriptor = childDescriptor;
}
assert(condition, msg = '') {
if (condition !== true) {
this.error(GENERIC_FUNCTION_ERROR + msg);
}
}
error(msg) {
msg = msg
.replace('{parent}', this.parentNotation)
.replace('{child}', this.childNotation);
// Replace lazily, because they actually might not
// be available in all cases
.replace('{parent}', m => this.parentNotation)
.replace('{child}', m => this.childNotation);
throw new SyntaxError(msg);

@@ -43,20 +113,74 @@ }

function checkDataDescriptors(parent, child, reportor) {
function checkFunctionSignatures(parent: Function, child: Function, reporter) {
reporter.assert(parent.length === child.length);
}
function checkDataDescriptors(parent, child, reporter) {
const parentValueType = typeof parent.value;
const childValueType = typeof child.value;
if (parentValueType === 'undefined' && childValueType === 'undefined') {
// class properties can be any expression, which isn't ran until the
// the instance is created, so we can't reliably get type information
// for them yet (per spec). Perhaps when Babel includes flow-type info
// in runtime? Tried regex solutions, but super hacky and only feasible
// on primitives, which is confusing for usage...
reporter.error(`descriptor values are both undefined. (class properties are are not currently supported)'`);
}
if (parentValueType !== childValueType) {
reportor.error(`Descriptor value types do not match. {parent} is "${parentValueType}", {child} is "${childValueType}"`);
const isFunctionOverUndefined = (childValueType === 'function' && parentValueType === undefined);
// Even though we don't support class properties, this
// will still handle more than just functions, just in case.
// Shadowing an undefined value is an error if the inherited
// value was undefined (usually a class property, not a method)
if (isFunctionOverUndefined || parentValueType !== undefined) {
reporter.error(`value types do not match. {parent} is "${parentValueType}", {child} is "${childValueType}"`);
}
}
// Switch, in preparation for supporting more types
switch (childValueType) {
case 'function':
checkFunctionSignatures(parent.value, child.value, reporter);
break;
default:
reporter.error(`Unexpected error. Please file a bug with: {parent} is "${parentValueType}", {child} is "${childValueType}"`);
break;
}
}
function checkAccessorDescriptors(parent, child, reportor) {
function checkAccessorDescriptors(parent, child, reporter) {
const parentHasGetter = typeof parent.get === 'function';
const childHasGetter = typeof child.get === 'function';
const parentHasSetter = typeof parent.set === 'function';
const childHasSetter = typeof child.set === 'function';
if (parentHasGetter || childHasGetter) {
if (!parentHasGetter && parentHasSetter) {
reporter.error(`{parent} is setter but {child} is getter`);
}
if (!childHasGetter && childHasSetter) {
reporter.error(`{parent} is getter but {child} is setter`);
}
checkFunctionSignatures(parent.get, child.get, reporter);
}
if (parentHasSetter || childHasSetter) {
if (!parentHasSetter && parentHasGetter) {
reporter.error(`{parent} is getter but {child} is setter`);
}
if (!childHasSetter && childHasGetter) {
reporter.error(`{parent} is setter but {child} is getter`);
}
checkFunctionSignatures(parent.set, child.set, reporter);
}
}
function checkDescriptors(parent, child, reportor) {
if (parent === undefined) {
reportor.error(`{child} marked as @override but {parent} was not defined (perhaps misspelled?)`);
}
function checkDescriptors(parent, child, reporter) {
const parentType = getDescriptorType(parent);

@@ -66,3 +190,3 @@ const childType = getDescriptorType(child);

if (parentType !== childType) {
reportor.error(`Descriptor types do not match. {parent} is "${parentType}", {child} is "${childType}"`);
reporter.error(`descriptor types do not match. {parent} is "${parentType}", {child} is "${childType}"`);
}

@@ -72,7 +196,7 @@

case 'data':
checkDataDescriptors(parent, child, reportor);
checkDataDescriptors(parent, child, reporter);
break;
case 'accessor':
checkAccessorDescriptors(parent, child, reportor);
checkAccessorDescriptors(parent, child, reporter);
break;

@@ -82,10 +206,36 @@ }

const suggestionTransforms = [
(key) => key.toLowerCase(),
(key) => key.toUpperCase(),
(key) => key + 's',
(key) => key.slice(0, -1),
(key) => key.slice(1, key.length),
];
function findPossibleAlternatives(superKlass, key) {
for (const fn of suggestionTransforms) {
const suggestion = fn(key);
if (suggestion in superKlass) {
return suggestion;
}
}
return null;
}
export function override(klass, key, descriptor) {
descriptor.key = key;
const superKlass = Object.getPrototypeOf(klass);
const superDescriptor = Object.getOwnPropertyDescriptor(superKlass, key);
const reportor = new SyntaxErrorReporter(key, superKlass, klass);
checkDescriptors(superDescriptor, descriptor, reportor);
const reporter = new SyntaxErrorReporter(superKlass, klass, superDescriptor, descriptor);
if (superDescriptor === undefined) {
const suggestedKey = findPossibleAlternatives(superKlass, key);
const suggestion = suggestedKey ? `\n\n Did you mean "${suggestedKey}"?` : '';
reporter.error(`No descriptor matching {child} was found on the prototype chain.${suggestion}`);
}
checkDescriptors(superDescriptor, descriptor, reporter);
return descriptor;
}
}

2

package.json
{
"name": "core-decorators",
"version": "0.0.1-broken",
"version": "0.0.1",
"description": "Library of ES7 decorators inspired by languages that come with built-ins like @override, @deprecated, etc",

@@ -5,0 +5,0 @@ "main": "index.js",

# core-decorators.js
Library of ES7 decorators inspired by languages that come with built-ins like @override, @deprecated, etc
Library of ES7 decorators inspired by languages that come with built-ins like @​override, @​deprecated, etc

@@ -16,5 +16,14 @@ The idea is these decorators would be used to ensure code sanity, but would be removed in production builds via a Babel plugin.

kickDog() {}
// SyntaxError: Parent#kickDog has two parameters but Child#kickDog has none
// > Parent#kickDog(first, second)
// SyntaxError: Child#kickDog() does not properly override Parent#kickDog(first, second)
}
// or
class Child extends Parent {
@override
kickDogs() {}
// SyntaxError: No descriptor matching Child#kickDogs() was found on the prototype chain.
//
// Did you mean "kickDog"?
}
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc