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

@player-ui/player

Package Overview
Dependencies
Maintainers
2
Versions
294
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@player-ui/player - npm Package Compare versions

Comparing version 0.3.1--canary.107.3859 to 0.3.1--canary.107.4249

dist/player.dev.js

12

package.json
{
"name": "@player-ui/player",
"version": "0.3.1--canary.107.3859",
"version": "0.3.1--canary.107.4249",
"private": false,

@@ -10,8 +10,8 @@ "publishConfig": {

"dependencies": {
"@player-ui/partial-match-registry": "0.3.1--canary.107.3859",
"@player-ui/types": "0.3.1--canary.107.3859",
"@player-ui/partial-match-registry": "0.3.1--canary.107.4249",
"@player-ui/types": "0.3.1--canary.107.4249",
"dequal": "^2.0.2",
"p-defer": "^3.0.0",
"queue-microtask": "^1.2.3",
"tapable-ts": "^0.1.0",
"tapable-ts": "^0.2.3",
"nested-error-stacks": "^2.1.1",

@@ -24,2 +24,3 @@ "@types/nested-error-stacks": "^2.1.0",

"timm": "^1.6.2",
"error-polyfill": "^0.1.3",
"@babel/runtime": "7.15.4"

@@ -69,3 +70,4 @@ },

}
]
],
"bundle": "./dist/player.prod.js"
}
import NestedError from 'nested-error-stacks';
import type { SyncWaterfallHook } from 'tapable-ts';
import type { PathNode, AnyNode } from '../binding-grammar';
import { findInArray, maybeConvertToNum } from './utils';
import { maybeConvertToNum } from '.';
import { findInArray } from './utils';
export interface NormalizedResult {

@@ -9,0 +7,0 @@ /** The normalized path */

@@ -30,3 +30,3 @@ import { SyncHook, SyncWaterfallHook, SyncBailHook } from 'tapable-ts';

onGet: new SyncHook<[any, any]>(),
onUpdate: new SyncHook<[Updates]>(),
onUpdate: new SyncHook<[Updates, DataModelOptions | undefined]>(),

@@ -161,4 +161,6 @@ format: new SyncWaterfallHook<[any, BindingInstance]>(),

this.hooks.onSet.call(normalizedTransaction);
if (setUpdates.length > 0) {
this.hooks.onUpdate.call(setUpdates);
this.hooks.onUpdate.call(setUpdates, options);
}

@@ -165,0 +167,0 @@

@@ -15,2 +15,3 @@ import type { Validation } from '@player-ui/types';

WarningValidationResponse,
StrongOrWeakBinding,
} from '../../validator';

@@ -330,7 +331,9 @@ import { ValidationMiddleware, ValidatorRegistry } from '../../validator';

// return validation issues directly on bindings first
if (strongValidation?.get()) return strongValidation.get();
if (strongValidation?.get()?.severity === 'error') {
return strongValidation.get();
}
// if none, check to see any validations this binding may be a weak ref of and return
const newInvalidBindings: Set<BindingInstance> = new Set();
for (const [, weakValidation] of Array.from(this.validations)) {
const newInvalidBindings: Set<StrongOrWeakBinding> = new Set();
this.validations.forEach((weakValidation, strongBinding) => {
if (

@@ -341,10 +344,17 @@ caresAboutDataChanges(

) &&
weakValidation?.get()
weakValidation?.get()?.severity === 'error'
) {
weakValidation?.weakBindings.forEach(
newInvalidBindings.add,
newInvalidBindings
);
weakValidation?.weakBindings.forEach((weakBinding) => {
weakBinding === strongBinding
? newInvalidBindings.add({
binding: weakBinding,
isStrong: true,
})
: newInvalidBindings.add({
binding: weakBinding,
isStrong: false,
});
});
}
}
});

@@ -382,3 +392,6 @@ if (newInvalidBindings.size > 0) {

if (originalValue !== withoutDefault) {
this.options.model.set([[binding, originalValue]]);
// Don't trigger updates when setting the default value
this.options.model.set([[binding, originalValue]], {
silent: true,
});
}

@@ -459,3 +472,3 @@

context,
binding
vBinding
);

@@ -590,3 +603,3 @@ return response ? { message: response.message } : undefined;

for (const b of this.getBindings()) {
this.getBindings().forEach((b) => {
const invalid = this.getValidationForBinding(b)?.get();

@@ -603,3 +616,3 @@

}
}
});

@@ -606,0 +619,0 @@ return {

@@ -44,2 +44,7 @@ import { SyncHook } from 'tapable-ts';

/**
* A flag to indicate that this update should happen silently
*/
silent?: boolean;
/** Other context associated with this request */

@@ -46,0 +51,0 @@ context?: {

import { SyncWaterfallHook, SyncBailHook } from 'tapable-ts';
import parse from './parser';
import * as DEFAULT_EXPRESSION_HANDLERS from './evaluator-functions';
import { isExpressionNode } from './types';
import type {

@@ -12,3 +13,2 @@ ExpressionNode,

} from './types';
import { isExpressionNode } from '.';

@@ -15,0 +15,0 @@ /** a && b -- but handles short cutting if the first value is false */

@@ -5,3 +5,3 @@ /* eslint @typescript-eslint/no-use-before-define: 0 */

*/
import type { ExpressionNode, ExpressionNodeType } from './types';
import type { ExpressionNode, ExpressionNodeType, NodeLocation } from './types';
import { ExpNodeOpaqueIdentifier } from './types';

@@ -84,2 +84,14 @@

/** Create a new location marker that spans both nodes */
function createSpanningLocation(start?: NodeLocation, end?: NodeLocation) {
if (!start || !end) {
return;
}
return {
start: start.start,
end: end.end,
};
}
/** Get return the longest key length of any object */

@@ -126,3 +138,4 @@ function getMaxKeyLen(obj: object): number {

left: string,
right: string
right: string,
location?: NodeLocation
) {

@@ -152,2 +165,3 @@ let type: ExpressionNodeType;

right,
location,
};

@@ -197,2 +211,14 @@ }

/** Create a location object */
const getLocation = (startChar: number) => {
return {
start: {
character: startChar,
},
end: {
character: index,
},
};
};
/** Grab the char at the index from the expression */

@@ -225,2 +251,4 @@ function exprI(i: number) {

let chCode;
const startCharIndex = index;
// get rid of OCURL_CODE

@@ -232,3 +260,2 @@ ++index;

chCode = exprICode(index);
// check for end

@@ -254,3 +281,2 @@ if (chCode === CCURL_CODE) {

gobbleSpaces();
// remove colon

@@ -269,3 +295,2 @@ if (exprICode(index) === COLON_CODE) {

chCode = exprICode(index);
if (chCode === COMMA_CODE) {

@@ -294,2 +319,3 @@ index++;

attributes,
location: getLocation(startCharIndex),
};

@@ -303,3 +329,2 @@ }

let ch = exprICode(index);
// Space or tab

@@ -317,2 +342,3 @@ while (ch === 32 || ch === 9) {

gobbleSpaces();
const startCharIndex = index;

@@ -344,2 +370,3 @@ if (index < length && exprICode(index) === QUMARK_CODE) {

alternate,
location: getLocation(startCharIndex),
};

@@ -369,3 +396,2 @@ }

index += tcLen;
return toCheck;

@@ -412,3 +438,2 @@ }

biop = gobbleBinaryOp();
while (biop) {

@@ -428,3 +453,8 @@ prec = binaryPrecedence(biop);

left = stack.pop();
node = createBinaryExpression(biop, left, right);
node = createBinaryExpression(
biop,
left,
right,
createSpanningLocation(left.location, right.location)
);
stack.push(node);

@@ -447,3 +477,8 @@ }

while (i > 1) {
node = createBinaryExpression(stack[i - 1].value, stack[i - 2], node);
node = createBinaryExpression(
stack[i - 1].value,
stack[i - 2],
node,
createSpanningLocation(stack[i - 2].location, node.location)
);
i -= 2;

@@ -462,2 +497,3 @@ }

const ch = exprICode(index);
const startCharIndex = index;

@@ -499,3 +535,2 @@ if (isDecimalDigit(ch) || ch === PERIOD_CODE) {

index += tcLen;
return {

@@ -507,2 +542,3 @@ __id: ExpNodeOpaqueIdentifier,

prefix: true,
location: getLocation(startCharIndex),
};

@@ -523,2 +559,3 @@ }

let num = '';
const startCharIndex = index;

@@ -539,3 +576,2 @@ while (isDecimalDigit(exprICode(index))) {

let ch = exprI(index);
if (ch === 'e' || ch === 'E') {

@@ -562,3 +598,2 @@ // Exponent marker

const chCode = exprICode(index);
// Check to make sure this isn't a variable name that start with a number (123abc)

@@ -579,2 +614,3 @@ if (isIdentifierStart(chCode)) {

raw: num,
location: getLocation(startCharIndex),
};

@@ -591,2 +627,3 @@ }

let closed = false;
const startCharIndex = index;

@@ -641,2 +678,3 @@ while (index < length) {

raw: `${quote}${str}${quote}`,
location: getLocation(startCharIndex),
};

@@ -653,5 +691,5 @@ }

let openBraceCount = 1;
const startCharIndex = index;
index += 2; // Skip the {{
while (index < length) {

@@ -687,2 +725,3 @@ const ch = exprI(index++);

ref: str,
location: getLocation(startCharIndex),
};

@@ -709,3 +748,2 @@ }

ch = exprICode(index);
if (isIdentifierPart(ch)) {

@@ -726,2 +764,3 @@ index++;

raw: identifier,
location: getLocation(start),
};

@@ -734,2 +773,3 @@ }

type: 'ThisExpression',
location: getLocation(start),
};

@@ -742,2 +782,3 @@ }

name: identifier,
location: getLocation(start),
};

@@ -796,3 +837,3 @@ }

charIndex === OPAREN_CODE ? gobbleGroup() : gobbleIdentifier();
const startCharIndex = index;
gobbleSpaces();

@@ -817,2 +858,3 @@ charIndex = exprICode(index);

property: gobbleIdentifier(),
location: getLocation(startCharIndex),
};

@@ -826,2 +868,3 @@ } else if (charIndex === OBRACK_CODE) {

property: gobbleExpression(),
location: getLocation(startCharIndex),
};

@@ -844,2 +887,3 @@

callTarget: node,
location: getLocation(startCharIndex),
};

@@ -856,3 +900,3 @@ }

/**
* Responsible for parsing a group within parentheses `()`
* Responsible for parsing a group of things within parentheses `()`
* This function assumes that it needs to gobble the opening parenthesis

@@ -870,3 +914,2 @@ * and then tries to gobble everything within that parenthesis, assuming

index++;
return node;

@@ -884,2 +927,3 @@ }

function gobbleArray() {
const startCharIndex = index;
index++;

@@ -891,2 +935,3 @@

elements: gobbleArguments(CBRACK_CODE),
location: getLocation(startCharIndex),
};

@@ -928,3 +973,4 @@ }

body: nodes,
location: getLocation(0),
};
}

@@ -59,2 +59,18 @@ import type { DataModelWithParser } from '../data';

export interface NodePosition {
/** The character location */
character: number;
}
export interface NodeLocation {
// We only care about the character offset, not the line/column for now
// But making these objects allows us to add more (like line number) later
/** The start of the node */
start: NodePosition;
/** The end of the node */
end: NodePosition;
}
export interface BaseNode<T> {

@@ -66,2 +82,5 @@ /** The thing to discriminate the AST type on */

__id: typeof ExpNodeOpaqueIdentifier;
/** The location of the node in the source expression string */
location?: NodeLocation;
}

@@ -93,9 +112,5 @@

export interface LogicalNode extends BaseNode<'LogicalExpression'> {
/** The left hand side of the equation */
left: any;
/** The right hand side of the equation */
right: any;
export interface LogicalNode
extends BaseNode<'LogicalExpression'>,
DirectionalNode {
/** The logical operation to perform on the nodes */

@@ -110,3 +125,3 @@ operator: string;

/** The single argument that the operation should be performed on */
argument: any;
argument: ExpressionNode;
}

@@ -125,6 +140,6 @@

/** The property name of the object */
key: any;
key: ExpressionNode;
/** the associated value */
value: any;
value: ExpressionNode;
}>;

@@ -163,3 +178,3 @@ }

/** The arguments to the function */
args: any[];
args: ExpressionNode[];

@@ -172,3 +187,3 @@ /** The function name */

/** The items in an array */
elements: any[];
elements: ExpressionNode[];
}

@@ -175,0 +190,0 @@

@@ -1,2 +0,7 @@

import type { ExpressionHandler } from './types';
import type {
ExpressionHandler,
ExpressionNode,
NodeLocation,
NodePosition,
} from './types';

@@ -9,1 +14,119 @@ /** Generates a function by removing the first context argument */

}
/** Checks if the location includes the target position */
function isInRange(position: NodePosition, location: NodeLocation) {
return (
position.character >= location.start.character &&
position.character <= location.end.character
);
}
/** Get the node in the expression that's closest to the desired position */
export function findClosestNodeAtPosition(
node: ExpressionNode,
position: NodePosition
): ExpressionNode | undefined {
// This is just mapping recursively over nodes in the tree
// eslint-disable-next-line default-case
switch (node.type) {
case 'Modification':
case 'Assignment':
case 'LogicalExpression':
case 'BinaryExpression': {
const check =
findClosestNodeAtPosition(node.left, position) ??
findClosestNodeAtPosition(node.right, position);
if (check) {
return check;
}
break;
}
case 'UnaryExpression': {
const checkArg = findClosestNodeAtPosition(node.argument, position);
if (checkArg) {
return checkArg;
}
break;
}
case 'MemberExpression': {
const checkObject =
findClosestNodeAtPosition(node.object, position) ??
findClosestNodeAtPosition(node.property, position);
if (checkObject) {
return checkObject;
}
break;
}
case 'ConditionalExpression': {
const checkObject =
findClosestNodeAtPosition(node.test, position) ??
findClosestNodeAtPosition(node.consequent, position) ??
findClosestNodeAtPosition(node.alternate, position);
if (checkObject) {
return checkObject;
}
break;
}
case 'ArrayExpression':
case 'Compound': {
const elements =
node.type === 'ArrayExpression' ? node.elements : node.body;
const anyElements = elements.find((e) =>
findClosestNodeAtPosition(e, position)
);
if (anyElements) {
return anyElements;
}
break;
}
case 'Object': {
const checkObject = node.attributes.reduce<ExpressionNode | undefined>(
(found, next) => {
return (
found ??
findClosestNodeAtPosition(next.key, position) ??
findClosestNodeAtPosition(next.value, position)
);
},
undefined
);
if (checkObject) {
return checkObject;
}
break;
}
case 'CallExpression': {
const anyArgs =
node.args.find((arg) => {
return findClosestNodeAtPosition(arg, position);
}) ?? findClosestNodeAtPosition(node.callTarget, position);
if (anyArgs) {
return anyArgs;
}
break;
}
}
// Lastly check for yourself
if (node.location && isInRange(position, node.location)) {
return node;
}
}

@@ -33,4 +33,4 @@ import { setIn } from 'timm';

// Variables injected at build time
const PLAYER_VERSION = '0.3.1--canary.107.3859';
const COMMIT = '7a617a91a3f46673d3ea9fdcce3e89fc5677390c';
const PLAYER_VERSION = '0.3.1--canary.107.4249';
const COMMIT = '520beeeba13f2d918991c15df954bf337f559f05';

@@ -290,6 +290,7 @@ export interface PlayerPlugin {

flow.hooks.beforeTransition.tap('player', (state, transitionVal) => {
if (
state.onEnd &&
(state.transitions[transitionVal] || state.transitions['*'])
) {
/** Checks to see if there are any transitions for a specific transition state (i.e. next, back). If not, it will default to * */
const computedTransitionVal = state.transitions[transitionVal]
? transitionVal
: '*';
if (state.onEnd && state.transitions[computedTransitionVal]) {
if (typeof state.onEnd === 'object' && 'exp' in state.onEnd) {

@@ -302,10 +303,15 @@ expressionEvaluator?.evaluate(state.onEnd.exp);

if (!('transitions' in state) || !state.transitions[transitionVal]) {
/** If the transition does not exist, then do not resolve any expressions */
if (
!('transitions' in state) ||
!state.transitions[computedTransitionVal]
) {
return state;
}
/** resolves and sets the transition to the computed exp */
return setIn(
state,
['transitions', transitionVal],
resolveStrings(state.transitions[transitionVal])
['transitions', computedTransitionVal],
resolveStrings(state.transitions[computedTransitionVal])
) as any;

@@ -354,7 +360,16 @@ });

// This created a weird timing where this nested transition would happen before the view had a chance to respond to the first one
// Use a queueMicrotask to make sure the expression transition is outside the scope of the flow hook
// Additionally, because we are using queueMicrotask, errors could get swallowed in the detached queue
// Use a try catch and fail player explicitly if any errors are caught in the nested transition/state
queueMicrotask(() => {
flowController?.transition(
String(expressionEvaluator?.evaluate(exp))
);
try {
flowController?.transition(
String(expressionEvaluator?.evaluate(exp))
);
} catch (error) {
const state = this.getState();
if (error instanceof Error && state.status === 'in-progress') {
state.fail(error);
}
}
});

@@ -361,0 +376,0 @@ }

@@ -163,2 +163,3 @@ import { setIn } from 'timm';

case 'object': {
if (!val) return val;
// TODO: Do we care refs in keys?

@@ -165,0 +166,0 @@ const keys = Object.keys(val);

@@ -16,2 +16,12 @@ import { setIn } from 'timm';

/**
* A BindingInstance with an indicator of whether or not it's a strong binding
*/
export type StrongOrWeakBinding = {
/** BindingInstance in question */
binding: BindingInstance;
/** Boolean indicating whether the relevant BindingInstance is a strong binding */
isStrong: boolean;
};
/**
* Returns a validation object if the data is invalid or an set of BindingsInstances if the binding itself is a weak ref of another invalid validation

@@ -22,3 +32,3 @@ */

model: DataModelImpl
) => ValidationResponse | Set<BindingInstance> | undefined;
) => ValidationResponse | Set<StrongOrWeakBinding> | undefined;

@@ -65,3 +75,8 @@ /**

} else if (validations instanceof Set) {
invalidBindings.push(...validations);
validations.forEach((validation) => {
invalidBindings.push(validation.binding);
if (!validation.isStrong) {
nextTransaction.push([validation.binding, value]);
}
});
} else {

@@ -81,3 +96,6 @@ this.logger?.debug(

);
return next.set(nextTransaction, options);
const result = next.set(nextTransaction, options);
if (invalidBindings.length === 0) {
return result;
}
}

@@ -84,0 +102,0 @@

@@ -111,2 +111,8 @@ import { set } from 'timm';

export default class StringResolverPlugin implements ViewPlugin {
private propertiesToSkipCache: Map<string, Set<string>>;
constructor() {
this.propertiesToSkipCache = new Map();
}
applyResolver(resolver: Resolver) {

@@ -124,7 +130,23 @@ resolver.hooks.resolve.tap('string-resolver', (value, node, options) => {

/** Use specified properties to skip during string resolution, or default */
const propsToSkip = new Set<string>(
node.plugins?.stringResolver?.propertiesToSkip
? node.plugins?.stringResolver?.propertiesToSkip
: []
);
let propsToSkip: Set<string>;
if (node.type === NodeType.Asset || node.type === NodeType.View) {
propsToSkip = new Set(
node.plugins?.stringResolver?.propertiesToSkip ?? ['exp']
);
if (node.value?.id) {
this.propertiesToSkipCache.set(node.value.id, propsToSkip);
}
} else if (
node.parent?.type === NodeType.MultiNode &&
(node.parent?.parent?.type === NodeType.Asset ||
node.parent?.parent?.type === NodeType.View) &&
node.parent.parent.value?.id &&
this.propertiesToSkipCache.has(node.parent.parent.value.id)
) {
propsToSkip = this.propertiesToSkipCache.get(
node.parent.parent.value.id
) as Set<string>;
} else {
propsToSkip = new Set(['exp']);
}

@@ -131,0 +153,0 @@ const nodePath = findBasePath(node);

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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